Merge pull request #3622 from Microsoft/intersectionTypes
Intersection types
This commit is contained in:
commit
71c6433514
|
@ -140,6 +140,7 @@ namespace ts {
|
||||||
|
|
||||||
let tupleTypes: Map<TupleType> = {};
|
let tupleTypes: Map<TupleType> = {};
|
||||||
let unionTypes: Map<UnionType> = {};
|
let unionTypes: Map<UnionType> = {};
|
||||||
|
let intersectionTypes: Map<IntersectionType> = {};
|
||||||
let stringLiteralTypes: Map<StringLiteralType> = {};
|
let stringLiteralTypes: Map<StringLiteralType> = {};
|
||||||
let emitExtends = false;
|
let emitExtends = false;
|
||||||
let emitDecorate = false;
|
let emitDecorate = false;
|
||||||
|
@ -1575,8 +1576,8 @@ namespace ts {
|
||||||
else if (type.flags & TypeFlags.Tuple) {
|
else if (type.flags & TypeFlags.Tuple) {
|
||||||
writeTupleType(<TupleType>type);
|
writeTupleType(<TupleType>type);
|
||||||
}
|
}
|
||||||
else if (type.flags & TypeFlags.Union) {
|
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||||
writeUnionType(<UnionType>type, flags);
|
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, flags);
|
||||||
}
|
}
|
||||||
else if (type.flags & TypeFlags.Anonymous) {
|
else if (type.flags & TypeFlags.Anonymous) {
|
||||||
writeAnonymousType(<ObjectType>type, flags);
|
writeAnonymousType(<ObjectType>type, flags);
|
||||||
|
@ -1595,16 +1596,16 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTypeList(types: Type[], union: boolean) {
|
function writeTypeList(types: Type[], delimiter: SyntaxKind) {
|
||||||
for (let i = 0; i < types.length; i++) {
|
for (let i = 0; i < types.length; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (union) {
|
if (delimiter !== SyntaxKind.CommaToken) {
|
||||||
writeSpace(writer);
|
writeSpace(writer);
|
||||||
}
|
}
|
||||||
writePunctuation(writer, union ? SyntaxKind.BarToken : SyntaxKind.CommaToken);
|
writePunctuation(writer, delimiter);
|
||||||
writeSpace(writer);
|
writeSpace(writer);
|
||||||
}
|
}
|
||||||
writeType(types[i], union ? TypeFormatFlags.InElementType : TypeFormatFlags.None);
|
writeType(types[i], delimiter === SyntaxKind.CommaToken ? TypeFormatFlags.None : TypeFormatFlags.InElementType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1662,15 +1663,15 @@ namespace ts {
|
||||||
|
|
||||||
function writeTupleType(type: TupleType) {
|
function writeTupleType(type: TupleType) {
|
||||||
writePunctuation(writer, SyntaxKind.OpenBracketToken);
|
writePunctuation(writer, SyntaxKind.OpenBracketToken);
|
||||||
writeTypeList(type.elementTypes, /*union*/ false);
|
writeTypeList(type.elementTypes, SyntaxKind.CommaToken);
|
||||||
writePunctuation(writer, SyntaxKind.CloseBracketToken);
|
writePunctuation(writer, SyntaxKind.CloseBracketToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeUnionType(type: UnionType, flags: TypeFormatFlags) {
|
function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) {
|
||||||
if (flags & TypeFormatFlags.InElementType) {
|
if (flags & TypeFormatFlags.InElementType) {
|
||||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||||
}
|
}
|
||||||
writeTypeList(type.types, /*union*/ true);
|
writeTypeList(type.types, type.flags & TypeFlags.Union ? SyntaxKind.BarToken : SyntaxKind.AmpersandToken);
|
||||||
if (flags & TypeFormatFlags.InElementType) {
|
if (flags & TypeFormatFlags.InElementType) {
|
||||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||||
}
|
}
|
||||||
|
@ -1747,7 +1748,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
|
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(type);
|
let resolved = resolveStructuredTypeMembers(type);
|
||||||
if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
|
if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
|
||||||
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
||||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||||
|
@ -2082,6 +2083,7 @@ namespace ts {
|
||||||
case SyntaxKind.ArrayType:
|
case SyntaxKind.ArrayType:
|
||||||
case SyntaxKind.TupleType:
|
case SyntaxKind.TupleType:
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
|
case SyntaxKind.IntersectionType:
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return isDeclarationVisible(<Declaration>node.parent);
|
return isDeclarationVisible(<Declaration>node.parent);
|
||||||
|
|
||||||
|
@ -2704,7 +2706,7 @@ namespace ts {
|
||||||
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
||||||
// Resolving the members of a class requires us to resolve the base class of that class.
|
// Resolving the members of a class requires us to resolve the base class of that class.
|
||||||
// We force resolution here such that we catch circularities now.
|
// We force resolution here such that we catch circularities now.
|
||||||
resolveObjectOrUnionTypeMembers(baseConstructorType);
|
resolveStructuredTypeMembers(baseConstructorType);
|
||||||
}
|
}
|
||||||
if (!popTypeResolution()) {
|
if (!popTypeResolution()) {
|
||||||
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
||||||
|
@ -3034,7 +3036,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveTupleTypeMembers(type: TupleType) {
|
function resolveTupleTypeMembers(type: TupleType) {
|
||||||
let arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
|
let arrayType = resolveStructuredTypeMembers(createArrayType(getUnionType(type.elementTypes)));
|
||||||
let members = createTupleTypeMemberSymbols(type.elementTypes);
|
let members = createTupleTypeMemberSymbols(type.elementTypes);
|
||||||
addInheritedMembers(members, arrayType.properties);
|
addInheritedMembers(members, arrayType.properties);
|
||||||
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
||||||
|
@ -3100,6 +3102,26 @@ namespace ts {
|
||||||
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function intersectTypes(type1: Type, type2: Type): Type {
|
||||||
|
return !type1 ? type2 : !type2 ? type1 : getIntersectionType([type1, type2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveIntersectionTypeMembers(type: IntersectionType) {
|
||||||
|
// The members and properties collections are empty for intersection types. To get all properties of an
|
||||||
|
// intersection type use getPropertiesOfType (only the language service uses this).
|
||||||
|
let callSignatures: Signature[] = emptyArray;
|
||||||
|
let constructSignatures: Signature[] = emptyArray;
|
||||||
|
let stringIndexType: Type = undefined;
|
||||||
|
let numberIndexType: Type = undefined;
|
||||||
|
for (let t of type.types) {
|
||||||
|
callSignatures = concatenate(callSignatures, getSignaturesOfType(t, SignatureKind.Call));
|
||||||
|
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(t, SignatureKind.Construct));
|
||||||
|
stringIndexType = intersectTypes(stringIndexType, getIndexTypeOfType(t, IndexKind.String));
|
||||||
|
numberIndexType = intersectTypes(numberIndexType, getIndexTypeOfType(t, IndexKind.Number));
|
||||||
|
}
|
||||||
|
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||||
|
}
|
||||||
|
|
||||||
function resolveAnonymousTypeMembers(type: ObjectType) {
|
function resolveAnonymousTypeMembers(type: ObjectType) {
|
||||||
let symbol = type.symbol;
|
let symbol = type.symbol;
|
||||||
let members: SymbolTable;
|
let members: SymbolTable;
|
||||||
|
@ -3144,7 +3166,7 @@ namespace ts {
|
||||||
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveObjectOrUnionTypeMembers(type: ObjectType): ResolvedType {
|
function resolveStructuredTypeMembers(type: ObjectType): ResolvedType {
|
||||||
if (!(<ResolvedType>type).members) {
|
if (!(<ResolvedType>type).members) {
|
||||||
if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||||
resolveClassOrInterfaceMembers(<InterfaceType>type);
|
resolveClassOrInterfaceMembers(<InterfaceType>type);
|
||||||
|
@ -3158,6 +3180,9 @@ namespace ts {
|
||||||
else if (type.flags & TypeFlags.Union) {
|
else if (type.flags & TypeFlags.Union) {
|
||||||
resolveUnionTypeMembers(<UnionType>type);
|
resolveUnionTypeMembers(<UnionType>type);
|
||||||
}
|
}
|
||||||
|
else if (type.flags & TypeFlags.Intersection) {
|
||||||
|
resolveIntersectionTypeMembers(<IntersectionType>type);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
resolveTypeReferenceMembers(<TypeReference>type);
|
resolveTypeReferenceMembers(<TypeReference>type);
|
||||||
}
|
}
|
||||||
|
@ -3168,16 +3193,16 @@ namespace ts {
|
||||||
// Return properties of an object type or an empty array for other types
|
// Return properties of an object type or an empty array for other types
|
||||||
function getPropertiesOfObjectType(type: Type): Symbol[] {
|
function getPropertiesOfObjectType(type: Type): Symbol[] {
|
||||||
if (type.flags & TypeFlags.ObjectType) {
|
if (type.flags & TypeFlags.ObjectType) {
|
||||||
return resolveObjectOrUnionTypeMembers(<ObjectType>type).properties;
|
return resolveStructuredTypeMembers(<ObjectType>type).properties;
|
||||||
}
|
}
|
||||||
return emptyArray;
|
return emptyArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the given type is an object type and that type has a property by the given name, return
|
// If the given type is an object type and that type has a property by the given name,
|
||||||
// the symbol for that property. Otherwise return undefined.
|
// return the symbol for that property.Otherwise return undefined.
|
||||||
function getPropertyOfObjectType(type: Type, name: string): Symbol {
|
function getPropertyOfObjectType(type: Type, name: string): Symbol {
|
||||||
if (type.flags & TypeFlags.ObjectType) {
|
if (type.flags & TypeFlags.ObjectType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
if (hasProperty(resolved.members, name)) {
|
if (hasProperty(resolved.members, name)) {
|
||||||
let symbol = resolved.members[name];
|
let symbol = resolved.members[name];
|
||||||
if (symbolIsValue(symbol)) {
|
if (symbolIsValue(symbol)) {
|
||||||
|
@ -3187,20 +3212,23 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPropertiesOfUnionType(type: UnionType): Symbol[] {
|
function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
|
||||||
let result: Symbol[] = [];
|
for (let current of type.types) {
|
||||||
forEach(getPropertiesOfType(type.types[0]), prop => {
|
for (let prop of getPropertiesOfType(current)) {
|
||||||
let unionProp = getPropertyOfUnionType(type, prop.name);
|
getPropertyOfUnionOrIntersectionType(type, prop.name);
|
||||||
if (unionProp) {
|
|
||||||
result.push(unionProp);
|
|
||||||
}
|
}
|
||||||
});
|
// The properties of a union type are those that are present in all constituent types, so
|
||||||
return result;
|
// we only need to check the properties of the first type
|
||||||
|
if (type.flags & TypeFlags.Union) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return type.resolvedProperties ? symbolsToArray(type.resolvedProperties) : emptyArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPropertiesOfType(type: Type): Symbol[] {
|
function getPropertiesOfType(type: Type): Symbol[] {
|
||||||
type = getApparentType(type);
|
type = getApparentType(type);
|
||||||
return type.flags & TypeFlags.Union ? getPropertiesOfUnionType(<UnionType>type) : getPropertiesOfObjectType(type);
|
return type.flags & TypeFlags.UnionOrIntersection ? getPropertiesOfUnionOrIntersectionType(<UnionType>type) : getPropertiesOfObjectType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3235,24 +3263,33 @@ namespace ts {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createUnionProperty(unionType: UnionType, name: string): Symbol {
|
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
|
||||||
let types = unionType.types;
|
let types = containingType.types;
|
||||||
let props: Symbol[];
|
let props: Symbol[];
|
||||||
for (let current of types) {
|
for (let current of types) {
|
||||||
let type = getApparentType(current);
|
let type = getApparentType(current);
|
||||||
if (type !== unknownType) {
|
if (type !== unknownType) {
|
||||||
let prop = getPropertyOfType(type, name);
|
let prop = getPropertyOfType(type, name);
|
||||||
if (!prop || getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected)) {
|
if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) {
|
||||||
|
if (!props) {
|
||||||
|
props = [prop];
|
||||||
|
}
|
||||||
|
else if (!contains(props, prop)) {
|
||||||
|
props.push(prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (containingType.flags & TypeFlags.Union) {
|
||||||
|
// A union type requires the property to be present in all constituent types
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (!props) {
|
|
||||||
props = [prop];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
props.push(prop);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!props) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (props.length === 1) {
|
||||||
|
return props[0];
|
||||||
|
}
|
||||||
let propTypes: Type[] = [];
|
let propTypes: Type[] = [];
|
||||||
let declarations: Declaration[] = [];
|
let declarations: Declaration[] = [];
|
||||||
for (let prop of props) {
|
for (let prop of props) {
|
||||||
|
@ -3261,19 +3298,19 @@ namespace ts {
|
||||||
}
|
}
|
||||||
propTypes.push(getTypeOfSymbol(prop));
|
propTypes.push(getTypeOfSymbol(prop));
|
||||||
}
|
}
|
||||||
let result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.UnionProperty, name);
|
let result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name);
|
||||||
result.unionType = unionType;
|
result.containingType = containingType;
|
||||||
result.declarations = declarations;
|
result.declarations = declarations;
|
||||||
result.type = getUnionType(propTypes);
|
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPropertyOfUnionType(type: UnionType, name: string): Symbol {
|
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol {
|
||||||
let properties = type.resolvedProperties || (type.resolvedProperties = {});
|
let properties = type.resolvedProperties || (type.resolvedProperties = {});
|
||||||
if (hasProperty(properties, name)) {
|
if (hasProperty(properties, name)) {
|
||||||
return properties[name];
|
return properties[name];
|
||||||
}
|
}
|
||||||
let property = createUnionProperty(type, name);
|
let property = createUnionOrIntersectionProperty(type, name);
|
||||||
if (property) {
|
if (property) {
|
||||||
properties[name] = property;
|
properties[name] = property;
|
||||||
}
|
}
|
||||||
|
@ -3286,7 +3323,7 @@ namespace ts {
|
||||||
function getPropertyOfType(type: Type, name: string): Symbol {
|
function getPropertyOfType(type: Type, name: string): Symbol {
|
||||||
type = getApparentType(type);
|
type = getApparentType(type);
|
||||||
if (type.flags & TypeFlags.ObjectType) {
|
if (type.flags & TypeFlags.ObjectType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(type);
|
let resolved = resolveStructuredTypeMembers(type);
|
||||||
if (hasProperty(resolved.members, name)) {
|
if (hasProperty(resolved.members, name)) {
|
||||||
let symbol = resolved.members[name];
|
let symbol = resolved.members[name];
|
||||||
if (symbolIsValue(symbol)) {
|
if (symbolIsValue(symbol)) {
|
||||||
|
@ -3301,15 +3338,15 @@ namespace ts {
|
||||||
}
|
}
|
||||||
return getPropertyOfObjectType(globalObjectType, name);
|
return getPropertyOfObjectType(globalObjectType, name);
|
||||||
}
|
}
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||||
return getPropertyOfUnionType(<UnionType>type, name);
|
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSignaturesOfObjectOrUnionType(type: Type, kind: SignatureKind): Signature[] {
|
function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): Signature[] {
|
||||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
if (type.flags & TypeFlags.StructuredType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures;
|
return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures;
|
||||||
}
|
}
|
||||||
return emptyArray;
|
return emptyArray;
|
||||||
|
@ -3318,22 +3355,21 @@ namespace ts {
|
||||||
// Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
|
// Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
|
||||||
// maps primitive types and type parameters are to their apparent types.
|
// maps primitive types and type parameters are to their apparent types.
|
||||||
function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] {
|
function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] {
|
||||||
return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
|
return getSignaturesOfStructuredType(getApparentType(type), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeHasCallOrConstructSignatures(type: Type): boolean {
|
function typeHasCallOrConstructSignatures(type: Type): boolean {
|
||||||
let apparentType = getApparentType(type);
|
let apparentType = getApparentType(type);
|
||||||
if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
if (apparentType.flags & TypeFlags.StructuredType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
return resolved.callSignatures.length > 0
|
return resolved.callSignatures.length > 0 || resolved.constructSignatures.length > 0;
|
||||||
|| resolved.constructSignatures.length > 0;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): Type {
|
function getIndexTypeOfStructuredType(type: Type, kind: IndexKind): Type {
|
||||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
if (type.flags & TypeFlags.StructuredType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
return kind === IndexKind.String ? resolved.stringIndexType : resolved.numberIndexType;
|
return kind === IndexKind.String ? resolved.stringIndexType : resolved.numberIndexType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3341,7 +3377,7 @@ namespace ts {
|
||||||
// Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
|
// Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
|
||||||
// maps primitive types and type parameters are to their apparent types.
|
// maps primitive types and type parameters are to their apparent types.
|
||||||
function getIndexTypeOfType(type: Type, kind: IndexKind): Type {
|
function getIndexTypeOfType(type: Type, kind: IndexKind): Type {
|
||||||
return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
|
return getIndexTypeOfStructuredType(getApparentType(type), kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
|
// Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual
|
||||||
|
@ -3891,25 +3927,20 @@ namespace ts {
|
||||||
return links.resolvedType;
|
return links.resolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTypeToSortedSet(sortedSet: Type[], type: Type) {
|
function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) {
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & typeSetKind) {
|
||||||
addTypesToSortedSet(sortedSet, (<UnionType>type).types);
|
addTypesToSet(typeSet, (<UnionOrIntersectionType>type).types, typeSetKind);
|
||||||
}
|
}
|
||||||
else {
|
else if (!contains(typeSet, type)) {
|
||||||
let i = 0;
|
typeSet.push(type);
|
||||||
let id = type.id;
|
|
||||||
while (i < sortedSet.length && sortedSet[i].id < id) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i === sortedSet.length || sortedSet[i].id !== id) {
|
|
||||||
sortedSet.splice(i, 0, type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTypesToSortedSet(sortedTypes: Type[], types: Type[]) {
|
// Add the given types to the given type set. Order is preserved, duplicates are removed,
|
||||||
|
// and nested types of the given kind are flattened into the set.
|
||||||
|
function addTypesToSet(typeSet: Type[], types: Type[], typeSetKind: TypeFlags) {
|
||||||
for (let type of types) {
|
for (let type of types) {
|
||||||
addTypeToSortedSet(sortedTypes, type);
|
addTypeToSet(typeSet, type, typeSetKind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3951,6 +3982,10 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function compareTypeIds(type1: Type, type2: Type): number {
|
||||||
|
return type1.id - type2.id;
|
||||||
|
}
|
||||||
|
|
||||||
// The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
|
// The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
|
||||||
// is true when creating a union type from a type node and when instantiating a union type. In both of those
|
// is true when creating a union type from a type node and when instantiating a union type. In both of those
|
||||||
// cases subtype reduction has to be deferred to properly support recursive union types. For example, a
|
// cases subtype reduction has to be deferred to properly support recursive union types. For example, a
|
||||||
|
@ -3959,26 +3994,27 @@ namespace ts {
|
||||||
if (types.length === 0) {
|
if (types.length === 0) {
|
||||||
return emptyObjectType;
|
return emptyObjectType;
|
||||||
}
|
}
|
||||||
let sortedTypes: Type[] = [];
|
let typeSet: Type[] = [];
|
||||||
addTypesToSortedSet(sortedTypes, types);
|
addTypesToSet(typeSet, types, TypeFlags.Union);
|
||||||
|
typeSet.sort(compareTypeIds);
|
||||||
if (noSubtypeReduction) {
|
if (noSubtypeReduction) {
|
||||||
if (containsTypeAny(sortedTypes)) {
|
if (containsTypeAny(typeSet)) {
|
||||||
return anyType;
|
return anyType;
|
||||||
}
|
}
|
||||||
removeAllButLast(sortedTypes, undefinedType);
|
removeAllButLast(typeSet, undefinedType);
|
||||||
removeAllButLast(sortedTypes, nullType);
|
removeAllButLast(typeSet, nullType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
removeSubtypes(sortedTypes);
|
removeSubtypes(typeSet);
|
||||||
}
|
}
|
||||||
if (sortedTypes.length === 1) {
|
if (typeSet.length === 1) {
|
||||||
return sortedTypes[0];
|
return typeSet[0];
|
||||||
}
|
}
|
||||||
let id = getTypeListId(sortedTypes);
|
let id = getTypeListId(typeSet);
|
||||||
let type = unionTypes[id];
|
let type = unionTypes[id];
|
||||||
if (!type) {
|
if (!type) {
|
||||||
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(sortedTypes));
|
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(typeSet));
|
||||||
type.types = sortedTypes;
|
type.types = typeSet;
|
||||||
type.reducedType = noSubtypeReduction ? undefined : type;
|
type.reducedType = noSubtypeReduction ? undefined : type;
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
|
@ -4010,6 +4046,40 @@ namespace ts {
|
||||||
return links.resolvedType;
|
return links.resolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do not perform supertype reduction on intersection types. Intersection types are created only by the &
|
||||||
|
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
|
||||||
|
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
|
||||||
|
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
|
||||||
|
// for intersections of types with signatures can be deterministic.
|
||||||
|
function getIntersectionType(types: Type[]): Type {
|
||||||
|
if (types.length === 0) {
|
||||||
|
return emptyObjectType;
|
||||||
|
}
|
||||||
|
let typeSet: Type[] = [];
|
||||||
|
addTypesToSet(typeSet, types, TypeFlags.Intersection);
|
||||||
|
if (containsTypeAny(typeSet)) {
|
||||||
|
return anyType;
|
||||||
|
}
|
||||||
|
if (typeSet.length === 1) {
|
||||||
|
return typeSet[0];
|
||||||
|
}
|
||||||
|
let id = getTypeListId(typeSet);
|
||||||
|
let type = intersectionTypes[id];
|
||||||
|
if (!type) {
|
||||||
|
type = intersectionTypes[id] = <IntersectionType>createObjectType(TypeFlags.Intersection | getWideningFlagsOfTypes(typeSet));
|
||||||
|
type.types = typeSet;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type {
|
||||||
|
let links = getNodeLinks(node);
|
||||||
|
if (!links.resolvedType) {
|
||||||
|
links.resolvedType = getIntersectionType(map(node.types, getTypeFromTypeNode));
|
||||||
|
}
|
||||||
|
return links.resolvedType;
|
||||||
|
}
|
||||||
|
|
||||||
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type {
|
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type {
|
||||||
let links = getNodeLinks(node);
|
let links = getNodeLinks(node);
|
||||||
if (!links.resolvedType) {
|
if (!links.resolvedType) {
|
||||||
|
@ -4067,6 +4137,8 @@ namespace ts {
|
||||||
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
|
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
|
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
|
||||||
|
case SyntaxKind.IntersectionType:
|
||||||
|
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node);
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
|
return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
|
||||||
case SyntaxKind.FunctionType:
|
case SyntaxKind.FunctionType:
|
||||||
|
@ -4254,6 +4326,9 @@ namespace ts {
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & TypeFlags.Union) {
|
||||||
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
|
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
|
||||||
}
|
}
|
||||||
|
if (type.flags & TypeFlags.Intersection) {
|
||||||
|
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -4294,7 +4369,7 @@ namespace ts {
|
||||||
|
|
||||||
function getTypeWithoutSignatures(type: Type): Type {
|
function getTypeWithoutSignatures(type: Type): Type {
|
||||||
if (type.flags & TypeFlags.ObjectType) {
|
if (type.flags & TypeFlags.ObjectType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
if (resolved.constructSignatures.length) {
|
if (resolved.constructSignatures.length) {
|
||||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
||||||
result.members = resolved.members;
|
result.members = resolved.members;
|
||||||
|
@ -4414,37 +4489,10 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let saveErrorInfo = errorInfo;
|
let saveErrorInfo = errorInfo;
|
||||||
if (source.flags & TypeFlags.Union || target.flags & TypeFlags.Union) {
|
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||||
if (relation === identityRelation) {
|
// We have type references to same target type, see if relationship holds for all type arguments
|
||||||
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union) {
|
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
||||||
if (result = unionTypeRelatedToUnionType(<UnionType>source, <UnionType>target)) {
|
return result;
|
||||||
if (result &= unionTypeRelatedToUnionType(<UnionType>target, <UnionType>source)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (source.flags & TypeFlags.Union) {
|
|
||||||
if (result = unionTypeRelatedToType(<UnionType>source, target, reportErrors)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (result = unionTypeRelatedToType(<UnionType>target, source, reportErrors)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (source.flags & TypeFlags.Union) {
|
|
||||||
if (result = unionTypeRelatedToType(<UnionType>source, target, reportErrors)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (result = typeRelatedToUnionType(source, <UnionType>target, reportErrors)) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
|
else if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
|
||||||
|
@ -4452,10 +4500,43 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
else if (relation !== identityRelation) {
|
||||||
// We have type references to same target type, see if relationship holds for all type arguments
|
// Note that the "each" checks must precede the "some" checks to produce the correct results
|
||||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
if (source.flags & TypeFlags.Union) {
|
||||||
return result;
|
if (result = eachTypeRelatedToType(<UnionType>source, target, reportErrors)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (target.flags & TypeFlags.Intersection) {
|
||||||
|
if (result = typeRelatedToEachType(source, <IntersectionType>target, reportErrors)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// It is necessary to try "each" checks on both sides because there may be nested "some" checks
|
||||||
|
// on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or
|
||||||
|
// A & B = (A & B) | (C & D).
|
||||||
|
if (source.flags & TypeFlags.Intersection) {
|
||||||
|
// If target is a union type the following check will report errors so we suppress them here
|
||||||
|
if (result = someTypeRelatedToType(<IntersectionType>source, target, reportErrors && !(target.flags & TypeFlags.Union))) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target.flags & TypeFlags.Union) {
|
||||||
|
if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
|
||||||
|
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
|
||||||
|
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
|
||||||
|
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4463,17 +4544,20 @@ namespace ts {
|
||||||
// it may hold in a structural comparison.
|
// it may hold in a structural comparison.
|
||||||
// Report structural errors only if we haven't reported any errors yet
|
// Report structural errors only if we haven't reported any errors yet
|
||||||
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
||||||
// identity relation does not use apparent type
|
// Identity relation does not use apparent type
|
||||||
let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
|
let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
|
||||||
if (sourceOrApparentType.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
|
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
|
||||||
|
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
|
||||||
|
// relates to X. Thus, we include intersection types on the source side here.
|
||||||
|
if (sourceOrApparentType.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) {
|
||||||
if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
|
if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
|
||||||
errorInfo = saveErrorInfo;
|
errorInfo = saveErrorInfo;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (source.flags & TypeFlags.TypeParameter && sourceOrApparentType.flags & TypeFlags.Union) {
|
else if (source.flags & TypeFlags.TypeParameter && sourceOrApparentType.flags & TypeFlags.UnionOrIntersection) {
|
||||||
// We clear the errors first because the following check often gives a better error than
|
// We clear the errors first because the following check often gives a better error than
|
||||||
// the union comparison above if it is applicable.
|
// the union or intersection comparison above if it is applicable.
|
||||||
errorInfo = saveErrorInfo;
|
errorInfo = saveErrorInfo;
|
||||||
if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
|
if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -4493,11 +4577,11 @@ namespace ts {
|
||||||
return Ternary.False;
|
return Ternary.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unionTypeRelatedToUnionType(source: UnionType, target: UnionType): Ternary {
|
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
|
||||||
let result = Ternary.True;
|
let result = Ternary.True;
|
||||||
let sourceTypes = source.types;
|
let sourceTypes = source.types;
|
||||||
for (let sourceType of sourceTypes) {
|
for (let sourceType of sourceTypes) {
|
||||||
let related = typeRelatedToUnionType(sourceType, target, false);
|
let related = typeRelatedToSomeType(sourceType, target, false);
|
||||||
if (!related) {
|
if (!related) {
|
||||||
return Ternary.False;
|
return Ternary.False;
|
||||||
}
|
}
|
||||||
|
@ -4506,7 +4590,7 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function typeRelatedToUnionType(source: Type, target: UnionType, reportErrors: boolean): Ternary {
|
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||||
let targetTypes = target.types;
|
let targetTypes = target.types;
|
||||||
for (let i = 0, len = targetTypes.length; i < len; i++) {
|
for (let i = 0, len = targetTypes.length; i < len; i++) {
|
||||||
let related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
|
let related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
|
||||||
|
@ -4517,7 +4601,31 @@ namespace ts {
|
||||||
return Ternary.False;
|
return Ternary.False;
|
||||||
}
|
}
|
||||||
|
|
||||||
function unionTypeRelatedToType(source: UnionType, target: Type, reportErrors: boolean): Ternary {
|
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||||
|
let result = Ternary.True;
|
||||||
|
let targetTypes = target.types;
|
||||||
|
for (let targetType of targetTypes) {
|
||||||
|
let related = isRelatedTo(source, targetType, reportErrors);
|
||||||
|
if (!related) {
|
||||||
|
return Ternary.False;
|
||||||
|
}
|
||||||
|
result &= related;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||||
|
let sourceTypes = source.types;
|
||||||
|
for (let i = 0, len = sourceTypes.length; i < len; i++) {
|
||||||
|
let related = isRelatedTo(sourceTypes[i], target, reportErrors && i === len - 1);
|
||||||
|
if (related) {
|
||||||
|
return related;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ternary.False;
|
||||||
|
}
|
||||||
|
|
||||||
|
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||||
let result = Ternary.True;
|
let result = Ternary.True;
|
||||||
let sourceTypes = source.types;
|
let sourceTypes = source.types;
|
||||||
for (let sourceType of sourceTypes) {
|
for (let sourceType of sourceTypes) {
|
||||||
|
@ -4572,7 +4680,7 @@ namespace ts {
|
||||||
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
|
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
|
||||||
// equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
|
// equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
|
||||||
// and issue an error. Otherwise, actually compare the structure of the two types.
|
// and issue an error. Otherwise, actually compare the structure of the two types.
|
||||||
function objectTypeRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
function objectTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||||
if (overflow) {
|
if (overflow) {
|
||||||
return Ternary.False;
|
return Ternary.False;
|
||||||
}
|
}
|
||||||
|
@ -4647,7 +4755,7 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function propertiesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||||
if (relation === identityRelation) {
|
if (relation === identityRelation) {
|
||||||
return propertiesIdenticalTo(source, target);
|
return propertiesIdenticalTo(source, target);
|
||||||
}
|
}
|
||||||
|
@ -4731,7 +4839,10 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function propertiesIdenticalTo(source: ObjectType, target: ObjectType): Ternary {
|
function propertiesIdenticalTo(source: Type, target: Type): Ternary {
|
||||||
|
if (!(source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType)) {
|
||||||
|
return Ternary.False;
|
||||||
|
}
|
||||||
let sourceProperties = getPropertiesOfObjectType(source);
|
let sourceProperties = getPropertiesOfObjectType(source);
|
||||||
let targetProperties = getPropertiesOfObjectType(target);
|
let targetProperties = getPropertiesOfObjectType(target);
|
||||||
if (sourceProperties.length !== targetProperties.length) {
|
if (sourceProperties.length !== targetProperties.length) {
|
||||||
|
@ -4752,7 +4863,7 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function signaturesRelatedTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): Ternary {
|
function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: boolean): Ternary {
|
||||||
if (relation === identityRelation) {
|
if (relation === identityRelation) {
|
||||||
return signaturesIdenticalTo(source, target, kind);
|
return signaturesIdenticalTo(source, target, kind);
|
||||||
}
|
}
|
||||||
|
@ -4878,7 +4989,7 @@ namespace ts {
|
||||||
return result & isRelatedTo(s, t, reportErrors);
|
return result & isRelatedTo(s, t, reportErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
function signaturesIdenticalTo(source: ObjectType, target: ObjectType, kind: SignatureKind): Ternary {
|
function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary {
|
||||||
let sourceSignatures = getSignaturesOfType(source, kind);
|
let sourceSignatures = getSignaturesOfType(source, kind);
|
||||||
let targetSignatures = getSignaturesOfType(target, kind);
|
let targetSignatures = getSignaturesOfType(target, kind);
|
||||||
if (sourceSignatures.length !== targetSignatures.length) {
|
if (sourceSignatures.length !== targetSignatures.length) {
|
||||||
|
@ -4895,7 +5006,7 @@ namespace ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
function stringIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||||
if (relation === identityRelation) {
|
if (relation === identityRelation) {
|
||||||
return indexTypesIdenticalTo(IndexKind.String, source, target);
|
return indexTypesIdenticalTo(IndexKind.String, source, target);
|
||||||
}
|
}
|
||||||
|
@ -4920,7 +5031,7 @@ namespace ts {
|
||||||
return Ternary.True;
|
return Ternary.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
function numberIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
function numberIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||||
if (relation === identityRelation) {
|
if (relation === identityRelation) {
|
||||||
return indexTypesIdenticalTo(IndexKind.Number, source, target);
|
return indexTypesIdenticalTo(IndexKind.Number, source, target);
|
||||||
}
|
}
|
||||||
|
@ -4953,7 +5064,7 @@ namespace ts {
|
||||||
return Ternary.True;
|
return Ternary.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
function indexTypesIdenticalTo(indexKind: IndexKind, source: ObjectType, target: ObjectType): Ternary {
|
function indexTypesIdenticalTo(indexKind: IndexKind, source: Type, target: Type): Ternary {
|
||||||
let targetType = getIndexTypeOfType(target, indexKind);
|
let targetType = getIndexTypeOfType(target, indexKind);
|
||||||
let sourceType = getIndexTypeOfType(source, indexKind);
|
let sourceType = getIndexTypeOfType(source, indexKind);
|
||||||
if (!sourceType && !targetType) {
|
if (!sourceType && !targetType) {
|
||||||
|
@ -5337,11 +5448,11 @@ namespace ts {
|
||||||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target.flags & TypeFlags.Union) {
|
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||||
let targetTypes = (<UnionType>target).types;
|
let targetTypes = (<UnionOrIntersectionType>target).types;
|
||||||
let typeParameterCount = 0;
|
let typeParameterCount = 0;
|
||||||
let typeParameter: TypeParameter;
|
let typeParameter: TypeParameter;
|
||||||
// First infer to each type in union that isn't a type parameter
|
// First infer to each type in union or intersection that isn't a type parameter
|
||||||
for (let t of targetTypes) {
|
for (let t of targetTypes) {
|
||||||
if (t.flags & TypeFlags.TypeParameter && contains(context.typeParameters, t)) {
|
if (t.flags & TypeFlags.TypeParameter && contains(context.typeParameters, t)) {
|
||||||
typeParameter = <TypeParameter>t;
|
typeParameter = <TypeParameter>t;
|
||||||
|
@ -5351,16 +5462,19 @@ namespace ts {
|
||||||
inferFromTypes(source, t);
|
inferFromTypes(source, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If union contains a single naked type parameter, make a secondary inference to that type parameter
|
// Next, if target is a union type containing a single naked type parameter, make a
|
||||||
if (typeParameterCount === 1) {
|
// secondary inference to that type parameter. We don't do this for intersection types
|
||||||
|
// because in a target type like Foo & T we don't know how which parts of the source type
|
||||||
|
// should be matched by Foo and which should be inferred to T.
|
||||||
|
if (target.flags & TypeFlags.Union && typeParameterCount === 1) {
|
||||||
inferiority++;
|
inferiority++;
|
||||||
inferFromTypes(source, typeParameter);
|
inferFromTypes(source, typeParameter);
|
||||||
inferiority--;
|
inferiority--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (source.flags & TypeFlags.Union) {
|
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||||
// Source is a union type, infer from each consituent type
|
// Source is a union or intersection type, infer from each consituent type
|
||||||
let sourceTypes = (<UnionType>source).types;
|
let sourceTypes = (<UnionOrIntersectionType>source).types;
|
||||||
for (let sourceType of sourceTypes) {
|
for (let sourceType of sourceTypes) {
|
||||||
inferFromTypes(sourceType, target);
|
inferFromTypes(sourceType, target);
|
||||||
}
|
}
|
||||||
|
@ -6343,13 +6457,13 @@ namespace ts {
|
||||||
|
|
||||||
function getTypeOfPropertyOfContextualType(type: Type, name: string) {
|
function getTypeOfPropertyOfContextualType(type: Type, name: string) {
|
||||||
return applyToContextualType(type, t => {
|
return applyToContextualType(type, t => {
|
||||||
let prop = getPropertyOfObjectType(t, name);
|
let prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined;
|
||||||
return prop ? getTypeOfSymbol(prop) : undefined;
|
return prop ? getTypeOfSymbol(prop) : undefined;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIndexTypeOfContextualType(type: Type, kind: IndexKind) {
|
function getIndexTypeOfContextualType(type: Type, kind: IndexKind) {
|
||||||
return applyToContextualType(type, t => getIndexTypeOfObjectOrUnionType(t, kind));
|
return applyToContextualType(type, t => getIndexTypeOfStructuredType(t, kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the given contextual type is a tuple-like type
|
// Return true if the given contextual type is a tuple-like type
|
||||||
|
@ -6359,7 +6473,7 @@ namespace ts {
|
||||||
|
|
||||||
// Return true if the given contextual type provides an index signature of the given kind
|
// Return true if the given contextual type provides an index signature of the given kind
|
||||||
function contextualTypeHasIndexSignature(type: Type, kind: IndexKind): boolean {
|
function contextualTypeHasIndexSignature(type: Type, kind: IndexKind): boolean {
|
||||||
return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, t => getIndexTypeOfObjectOrUnionType(t, kind)) : getIndexTypeOfObjectOrUnionType(type, kind));
|
return !!(type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, t => getIndexTypeOfStructuredType(t, kind)) : getIndexTypeOfStructuredType(type, kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
// In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of
|
// In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of
|
||||||
|
@ -6496,7 +6610,7 @@ namespace ts {
|
||||||
// If the given type is an object or union type, if that type has a single signature, and if
|
// If the given type is an object or union type, if that type has a single signature, and if
|
||||||
// that signature is non-generic, return the signature. Otherwise return undefined.
|
// that signature is non-generic, return the signature. Otherwise return undefined.
|
||||||
function getNonGenericSignature(type: Type): Signature {
|
function getNonGenericSignature(type: Type): Signature {
|
||||||
let signatures = getSignaturesOfObjectOrUnionType(type, SignatureKind.Call);
|
let signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||||
if (signatures.length === 1) {
|
if (signatures.length === 1) {
|
||||||
let signature = signatures[0];
|
let signature = signatures[0];
|
||||||
if (!signature.typeParameters) {
|
if (!signature.typeParameters) {
|
||||||
|
@ -6538,7 +6652,7 @@ namespace ts {
|
||||||
// The signature set of all constituent type with call signatures should match
|
// The signature set of all constituent type with call signatures should match
|
||||||
// So number of signatures allowed is either 0 or 1
|
// So number of signatures allowed is either 0 or 1
|
||||||
if (signatureList &&
|
if (signatureList &&
|
||||||
getSignaturesOfObjectOrUnionType(current, SignatureKind.Call).length > 1) {
|
getSignaturesOfStructuredType(current, SignatureKind.Call).length > 1) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7691,7 +7805,7 @@ namespace ts {
|
||||||
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
|
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
|
||||||
function getSingleCallSignature(type: Type): Signature {
|
function getSingleCallSignature(type: Type): Signature {
|
||||||
if (type.flags & TypeFlags.ObjectType) {
|
if (type.flags & TypeFlags.ObjectType) {
|
||||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||||
if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
|
if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
|
||||||
resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
|
resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
|
||||||
return resolved.callSignatures[0];
|
return resolved.callSignatures[0];
|
||||||
|
@ -9131,8 +9245,8 @@ namespace ts {
|
||||||
if (type.flags & kind) {
|
if (type.flags & kind) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||||
let types = (<UnionType>type).types;
|
let types = (<UnionOrIntersectionType>type).types;
|
||||||
for (let current of types) {
|
for (let current of types) {
|
||||||
if (current.flags & kind) {
|
if (current.flags & kind) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -9143,13 +9257,13 @@ namespace ts {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if type has the given flags, or is a union type composed of types that all have those flags.
|
// Return true if type has the given flags, or is a union or intersection type composed of types that all have those flags.
|
||||||
function allConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean {
|
function allConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean {
|
||||||
if (type.flags & kind) {
|
if (type.flags & kind) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||||
let types = (<UnionType>type).types;
|
let types = (<UnionOrIntersectionType>type).types;
|
||||||
for (let current of types) {
|
for (let current of types) {
|
||||||
if (!(current.flags & kind)) {
|
if (!(current.flags & kind)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -10174,7 +10288,7 @@ namespace ts {
|
||||||
forEach(node.elementTypes, checkSourceElement);
|
forEach(node.elementTypes, checkSourceElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkUnionType(node: UnionTypeNode) {
|
function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) {
|
||||||
forEach(node.types, checkSourceElement);
|
forEach(node.types, checkSourceElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12951,7 +13065,8 @@ namespace ts {
|
||||||
case SyntaxKind.TupleType:
|
case SyntaxKind.TupleType:
|
||||||
return checkTupleType(<TupleTypeNode>node);
|
return checkTupleType(<TupleTypeNode>node);
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
return checkUnionType(<UnionTypeNode>node);
|
case SyntaxKind.IntersectionType:
|
||||||
|
return checkUnionOrIntersectionType(<UnionOrIntersectionTypeNode>node);
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return checkSourceElement((<ParenthesizedTypeNode>node).type);
|
return checkSourceElement((<ParenthesizedTypeNode>node).type);
|
||||||
case SyntaxKind.FunctionDeclaration:
|
case SyntaxKind.FunctionDeclaration:
|
||||||
|
@ -13593,10 +13708,10 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRootSymbols(symbol: Symbol): Symbol[] {
|
function getRootSymbols(symbol: Symbol): Symbol[] {
|
||||||
if (symbol.flags & SymbolFlags.UnionProperty) {
|
if (symbol.flags & SymbolFlags.SyntheticProperty) {
|
||||||
let symbols: Symbol[] = [];
|
let symbols: Symbol[] = [];
|
||||||
let name = symbol.name;
|
let name = symbol.name;
|
||||||
forEach(getSymbolLinks(symbol).unionType.types, t => {
|
forEach(getSymbolLinks(symbol).containingType.types, t => {
|
||||||
symbols.push(getPropertyOfType(t, name));
|
symbols.push(getPropertyOfType(t, name));
|
||||||
});
|
});
|
||||||
return symbols;
|
return symbols;
|
||||||
|
@ -13893,6 +14008,7 @@ namespace ts {
|
||||||
case SyntaxKind.TypeQuery:
|
case SyntaxKind.TypeQuery:
|
||||||
case SyntaxKind.TypeLiteral:
|
case SyntaxKind.TypeLiteral:
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
|
case SyntaxKind.IntersectionType:
|
||||||
case SyntaxKind.AnyKeyword:
|
case SyntaxKind.AnyKeyword:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -340,6 +340,8 @@ namespace ts {
|
||||||
return emitTupleType(<TupleTypeNode>type);
|
return emitTupleType(<TupleTypeNode>type);
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
return emitUnionType(<UnionTypeNode>type);
|
return emitUnionType(<UnionTypeNode>type);
|
||||||
|
case SyntaxKind.IntersectionType:
|
||||||
|
return emitIntersectionType(<IntersectionTypeNode>type);
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return emitParenType(<ParenthesizedTypeNode>type);
|
return emitParenType(<ParenthesizedTypeNode>type);
|
||||||
case SyntaxKind.FunctionType:
|
case SyntaxKind.FunctionType:
|
||||||
|
@ -416,6 +418,10 @@ namespace ts {
|
||||||
emitSeparatedList(type.types, " | ", emitType);
|
emitSeparatedList(type.types, " | ", emitType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function emitIntersectionType(type: IntersectionTypeNode) {
|
||||||
|
emitSeparatedList(type.types, " & ", emitType);
|
||||||
|
}
|
||||||
|
|
||||||
function emitParenType(type: ParenthesizedTypeNode) {
|
function emitParenType(type: ParenthesizedTypeNode) {
|
||||||
write("(");
|
write("(");
|
||||||
emitType(type.type);
|
emitType(type.type);
|
||||||
|
|
|
@ -115,7 +115,8 @@ namespace ts {
|
||||||
case SyntaxKind.TupleType:
|
case SyntaxKind.TupleType:
|
||||||
return visitNodes(cbNodes, (<TupleTypeNode>node).elementTypes);
|
return visitNodes(cbNodes, (<TupleTypeNode>node).elementTypes);
|
||||||
case SyntaxKind.UnionType:
|
case SyntaxKind.UnionType:
|
||||||
return visitNodes(cbNodes, (<UnionTypeNode>node).types);
|
case SyntaxKind.IntersectionType:
|
||||||
|
return visitNodes(cbNodes, (<UnionOrIntersectionTypeNode>node).types);
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return visitNode(cbNode, (<ParenthesizedTypeNode>node).type);
|
return visitNode(cbNode, (<ParenthesizedTypeNode>node).type);
|
||||||
case SyntaxKind.ObjectBindingPattern:
|
case SyntaxKind.ObjectBindingPattern:
|
||||||
|
@ -2401,22 +2402,30 @@ namespace ts {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseUnionTypeOrHigher(): TypeNode {
|
function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode {
|
||||||
let type = parseArrayTypeOrHigher();
|
let type = parseConstituentType();
|
||||||
if (token === SyntaxKind.BarToken) {
|
if (token === operator) {
|
||||||
let types = <NodeArray<TypeNode>>[type];
|
let types = <NodeArray<TypeNode>>[type];
|
||||||
types.pos = type.pos;
|
types.pos = type.pos;
|
||||||
while (parseOptional(SyntaxKind.BarToken)) {
|
while (parseOptional(operator)) {
|
||||||
types.push(parseArrayTypeOrHigher());
|
types.push(parseConstituentType());
|
||||||
}
|
}
|
||||||
types.end = getNodeEnd();
|
types.end = getNodeEnd();
|
||||||
let node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
|
let node = <UnionOrIntersectionTypeNode>createNode(kind, type.pos);
|
||||||
node.types = types;
|
node.types = types;
|
||||||
type = finishNode(node);
|
type = finishNode(node);
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseIntersectionTypeOrHigher(): TypeNode {
|
||||||
|
return parseUnionOrIntersectionType(SyntaxKind.IntersectionType, parseArrayTypeOrHigher, SyntaxKind.AmpersandToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseUnionTypeOrHigher(): TypeNode {
|
||||||
|
return parseUnionOrIntersectionType(SyntaxKind.UnionType, parseIntersectionTypeOrHigher, SyntaxKind.BarToken);
|
||||||
|
}
|
||||||
|
|
||||||
function isStartOfFunctionType(): boolean {
|
function isStartOfFunctionType(): boolean {
|
||||||
if (token === SyntaxKind.LessThanToken) {
|
if (token === SyntaxKind.LessThanToken) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -191,6 +191,7 @@ namespace ts {
|
||||||
ArrayType,
|
ArrayType,
|
||||||
TupleType,
|
TupleType,
|
||||||
UnionType,
|
UnionType,
|
||||||
|
IntersectionType,
|
||||||
ParenthesizedType,
|
ParenthesizedType,
|
||||||
// Binding patterns
|
// Binding patterns
|
||||||
ObjectBindingPattern,
|
ObjectBindingPattern,
|
||||||
|
@ -667,10 +668,14 @@ namespace ts {
|
||||||
elementTypes: NodeArray<TypeNode>;
|
elementTypes: NodeArray<TypeNode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UnionTypeNode extends TypeNode {
|
export interface UnionOrIntersectionTypeNode extends TypeNode {
|
||||||
types: NodeArray<TypeNode>;
|
types: NodeArray<TypeNode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UnionTypeNode extends UnionOrIntersectionTypeNode { }
|
||||||
|
|
||||||
|
export interface IntersectionTypeNode extends UnionOrIntersectionTypeNode { }
|
||||||
|
|
||||||
export interface ParenthesizedTypeNode extends TypeNode {
|
export interface ParenthesizedTypeNode extends TypeNode {
|
||||||
type: TypeNode;
|
type: TypeNode;
|
||||||
}
|
}
|
||||||
|
@ -1573,7 +1578,7 @@ namespace ts {
|
||||||
Merged = 0x02000000, // Merged symbol (created during program binding)
|
Merged = 0x02000000, // Merged symbol (created during program binding)
|
||||||
Transient = 0x04000000, // Transient symbol (created during type check)
|
Transient = 0x04000000, // Transient symbol (created during type check)
|
||||||
Prototype = 0x08000000, // Prototype property (no source representation)
|
Prototype = 0x08000000, // Prototype property (no source representation)
|
||||||
UnionProperty = 0x10000000, // Property in union type
|
SyntheticProperty = 0x10000000, // Property in union or intersection type
|
||||||
Optional = 0x20000000, // Optional property
|
Optional = 0x20000000, // Optional property
|
||||||
ExportStar = 0x40000000, // Export * declaration
|
ExportStar = 0x40000000, // Export * declaration
|
||||||
|
|
||||||
|
@ -1652,7 +1657,7 @@ namespace ts {
|
||||||
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
|
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
|
||||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||||
unionType?: UnionType; // Containing union type for union property
|
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
|
||||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||||
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
|
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
|
||||||
|
@ -1721,17 +1726,18 @@ namespace ts {
|
||||||
Interface = 0x00000800, // Interface
|
Interface = 0x00000800, // Interface
|
||||||
Reference = 0x00001000, // Generic type reference
|
Reference = 0x00001000, // Generic type reference
|
||||||
Tuple = 0x00002000, // Tuple
|
Tuple = 0x00002000, // Tuple
|
||||||
Union = 0x00004000, // Union
|
Union = 0x00004000, // Union (T | U)
|
||||||
Anonymous = 0x00008000, // Anonymous
|
Intersection = 0x00008000, // Intersection (T & U)
|
||||||
Instantiated = 0x00010000, // Instantiated anonymous type
|
Anonymous = 0x00010000, // Anonymous
|
||||||
|
Instantiated = 0x00020000, // Instantiated anonymous type
|
||||||
/* @internal */
|
/* @internal */
|
||||||
FromSignature = 0x00020000, // Created for signature assignment check
|
FromSignature = 0x00040000, // Created for signature assignment check
|
||||||
ObjectLiteral = 0x00040000, // Originates in an object literal
|
ObjectLiteral = 0x00080000, // Originates in an object literal
|
||||||
/* @internal */
|
/* @internal */
|
||||||
ContainsUndefinedOrNull = 0x00080000, // Type is or contains Undefined or Null type
|
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
|
||||||
/* @internal */
|
/* @internal */
|
||||||
ContainsObjectLiteral = 0x00100000, // Type is or contains object literal type
|
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
|
||||||
ESSymbol = 0x00200000, // Type of symbol primitive introduced in ES6
|
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||||
|
@ -1740,6 +1746,8 @@ namespace ts {
|
||||||
StringLike = String | StringLiteral,
|
StringLike = String | StringLiteral,
|
||||||
NumberLike = Number | Enum,
|
NumberLike = Number | Enum,
|
||||||
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
|
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
|
||||||
|
UnionOrIntersection = Union | Intersection,
|
||||||
|
StructuredType = ObjectType | Union | Intersection,
|
||||||
/* @internal */
|
/* @internal */
|
||||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral
|
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral
|
||||||
}
|
}
|
||||||
|
@ -1799,7 +1807,7 @@ namespace ts {
|
||||||
baseArrayType: TypeReference; // Array<T> where T is best common type of element types
|
baseArrayType: TypeReference; // Array<T> where T is best common type of element types
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UnionType extends Type {
|
export interface UnionOrIntersectionType extends Type {
|
||||||
types: Type[]; // Constituent types
|
types: Type[]; // Constituent types
|
||||||
/* @internal */
|
/* @internal */
|
||||||
reducedType: Type; // Reduced union type (all subtypes removed)
|
reducedType: Type; // Reduced union type (all subtypes removed)
|
||||||
|
@ -1807,9 +1815,13 @@ namespace ts {
|
||||||
resolvedProperties: SymbolTable; // Cache of resolved properties
|
resolvedProperties: SymbolTable; // Cache of resolved properties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UnionType extends UnionOrIntersectionType { }
|
||||||
|
|
||||||
|
export interface IntersectionType extends UnionOrIntersectionType { }
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
// Resolved object or union type
|
// Resolved object, union, or intersection type
|
||||||
export interface ResolvedType extends ObjectType, UnionType {
|
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
|
||||||
members: SymbolTable; // Properties by name
|
members: SymbolTable; // Properties by name
|
||||||
properties: Symbol[]; // Properties
|
properties: Symbol[]; // Properties
|
||||||
callSignatures: Signature[]; // Call signatures of type
|
callSignatures: Signature[]; // Call signatures of type
|
||||||
|
|
|
@ -3689,7 +3689,7 @@ namespace ts {
|
||||||
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
||||||
|
|
||||||
if (flags & SymbolFlags.Property) {
|
if (flags & SymbolFlags.Property) {
|
||||||
if (flags & SymbolFlags.UnionProperty) {
|
if (flags & SymbolFlags.SyntheticProperty) {
|
||||||
// If union property is result of union of non method (property/accessors/variables), it is labeled as property
|
// If union property is result of union of non method (property/accessors/variables), it is labeled as property
|
||||||
let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
|
let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
|
||||||
let rootSymbolFlags = rootSymbol.getFlags();
|
let rootSymbolFlags = rootSymbol.getFlags();
|
||||||
|
@ -5159,7 +5159,7 @@ namespace ts {
|
||||||
|
|
||||||
// if this symbol is visible from its parent container, e.g. exported, then bail out
|
// if this symbol is visible from its parent container, e.g. exported, then bail out
|
||||||
// if symbol correspond to the union property - bail out
|
// if symbol correspond to the union property - bail out
|
||||||
if (symbol.parent || (symbol.flags & SymbolFlags.UnionProperty)) {
|
if (symbol.parent || (symbol.flags & SymbolFlags.SyntheticProperty)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,26 +75,26 @@ function delint(sourceFile) {
|
||||||
delintNode(sourceFile);
|
delintNode(sourceFile);
|
||||||
function delintNode(node) {
|
function delintNode(node) {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case 195 /* ForStatement */:
|
case 196 /* ForStatement */:
|
||||||
case 196 /* ForInStatement */:
|
case 197 /* ForInStatement */:
|
||||||
case 194 /* WhileStatement */:
|
case 195 /* WhileStatement */:
|
||||||
case 193 /* DoStatement */:
|
case 194 /* DoStatement */:
|
||||||
if (node.statement.kind !== 188 /* Block */) {
|
if (node.statement.kind !== 189 /* Block */) {
|
||||||
report(node, "A looping statement's contents should be wrapped in a block body.");
|
report(node, "A looping statement's contents should be wrapped in a block body.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 192 /* IfStatement */:
|
case 193 /* IfStatement */:
|
||||||
var ifStatement = node;
|
var ifStatement = node;
|
||||||
if (ifStatement.thenStatement.kind !== 188 /* Block */) {
|
if (ifStatement.thenStatement.kind !== 189 /* Block */) {
|
||||||
report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.");
|
report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.");
|
||||||
}
|
}
|
||||||
if (ifStatement.elseStatement &&
|
if (ifStatement.elseStatement &&
|
||||||
ifStatement.elseStatement.kind !== 188 /* Block */ &&
|
ifStatement.elseStatement.kind !== 189 /* Block */ &&
|
||||||
ifStatement.elseStatement.kind !== 192 /* IfStatement */) {
|
ifStatement.elseStatement.kind !== 193 /* IfStatement */) {
|
||||||
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
|
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 177 /* BinaryExpression */:
|
case 178 /* BinaryExpression */:
|
||||||
var op = node.operatorToken.kind;
|
var op = node.operatorToken.kind;
|
||||||
if (op === 29 /* EqualsEqualsToken */ || op == 30 /* ExclamationEqualsToken */) {
|
if (op === 29 /* EqualsEqualsToken */ || op == 30 /* ExclamationEqualsToken */) {
|
||||||
report(node, "Use '===' and '!=='.");
|
report(node, "Use '===' and '!=='.");
|
||||||
|
|
14
tests/baselines/reference/contextualIntersectionType.js
Normal file
14
tests/baselines/reference/contextualIntersectionType.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//// [contextualIntersectionType.ts]
|
||||||
|
var x: { a: (s: string) => string } & { b: (n: number) => number };
|
||||||
|
x = {
|
||||||
|
a: s => s,
|
||||||
|
b: n => n
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//// [contextualIntersectionType.js]
|
||||||
|
var x;
|
||||||
|
x = {
|
||||||
|
a: function (s) { return s; },
|
||||||
|
b: function (n) { return n; }
|
||||||
|
};
|
23
tests/baselines/reference/contextualIntersectionType.symbols
Normal file
23
tests/baselines/reference/contextualIntersectionType.symbols
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/contextualIntersectionType.ts ===
|
||||||
|
var x: { a: (s: string) => string } & { b: (n: number) => number };
|
||||||
|
>x : Symbol(x, Decl(contextualIntersectionType.ts, 0, 3))
|
||||||
|
>a : Symbol(a, Decl(contextualIntersectionType.ts, 0, 8))
|
||||||
|
>s : Symbol(s, Decl(contextualIntersectionType.ts, 0, 13))
|
||||||
|
>b : Symbol(b, Decl(contextualIntersectionType.ts, 0, 39))
|
||||||
|
>n : Symbol(n, Decl(contextualIntersectionType.ts, 0, 44))
|
||||||
|
|
||||||
|
x = {
|
||||||
|
>x : Symbol(x, Decl(contextualIntersectionType.ts, 0, 3))
|
||||||
|
|
||||||
|
a: s => s,
|
||||||
|
>a : Symbol(a, Decl(contextualIntersectionType.ts, 1, 5))
|
||||||
|
>s : Symbol(s, Decl(contextualIntersectionType.ts, 2, 6))
|
||||||
|
>s : Symbol(s, Decl(contextualIntersectionType.ts, 2, 6))
|
||||||
|
|
||||||
|
b: n => n
|
||||||
|
>b : Symbol(b, Decl(contextualIntersectionType.ts, 2, 14))
|
||||||
|
>n : Symbol(n, Decl(contextualIntersectionType.ts, 3, 6))
|
||||||
|
>n : Symbol(n, Decl(contextualIntersectionType.ts, 3, 6))
|
||||||
|
|
||||||
|
};
|
||||||
|
|
27
tests/baselines/reference/contextualIntersectionType.types
Normal file
27
tests/baselines/reference/contextualIntersectionType.types
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/contextualIntersectionType.ts ===
|
||||||
|
var x: { a: (s: string) => string } & { b: (n: number) => number };
|
||||||
|
>x : { a: (s: string) => string; } & { b: (n: number) => number; }
|
||||||
|
>a : (s: string) => string
|
||||||
|
>s : string
|
||||||
|
>b : (n: number) => number
|
||||||
|
>n : number
|
||||||
|
|
||||||
|
x = {
|
||||||
|
>x = { a: s => s, b: n => n} : { a: (s: string) => string; b: (n: number) => number; }
|
||||||
|
>x : { a: (s: string) => string; } & { b: (n: number) => number; }
|
||||||
|
>{ a: s => s, b: n => n} : { a: (s: string) => string; b: (n: number) => number; }
|
||||||
|
|
||||||
|
a: s => s,
|
||||||
|
>a : (s: string) => string
|
||||||
|
>s => s : (s: string) => string
|
||||||
|
>s : string
|
||||||
|
>s : string
|
||||||
|
|
||||||
|
b: n => n
|
||||||
|
>b : (n: number) => number
|
||||||
|
>n => n : (n: number) => number
|
||||||
|
>n : number
|
||||||
|
>n : number
|
||||||
|
|
||||||
|
};
|
||||||
|
|
162
tests/baselines/reference/intersectionAndUnionTypes.errors.txt
Normal file
162
tests/baselines/reference/intersectionAndUnionTypes.errors.txt
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(19,1): error TS2322: Type 'A' is not assignable to type 'A & B'.
|
||||||
|
Type 'A' is not assignable to type 'B'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(20,1): error TS2322: Type 'B' is not assignable to type 'A & B'.
|
||||||
|
Type 'B' is not assignable to type 'A'.
|
||||||
|
Property 'a' is missing in type 'B'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(23,1): error TS2322: Type 'A | B' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
Type 'A' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
Type 'A' is not assignable to type 'C & D'.
|
||||||
|
Type 'A' is not assignable to type 'C'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(25,1): error TS2322: Type 'C | D' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
Type 'C' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
Type 'C' is not assignable to type 'C & D'.
|
||||||
|
Type 'C' is not assignable to type 'D'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(26,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A & B'.
|
||||||
|
Type 'C & D' is not assignable to type 'A & B'.
|
||||||
|
Type 'C & D' is not assignable to type 'A'.
|
||||||
|
Type 'D' is not assignable to type 'A'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(27,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A | B'.
|
||||||
|
Type 'C & D' is not assignable to type 'A | B'.
|
||||||
|
Type 'C & D' is not assignable to type 'B'.
|
||||||
|
Type 'D' is not assignable to type 'B'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(28,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C & D'.
|
||||||
|
Type 'A & B' is not assignable to type 'C & D'.
|
||||||
|
Type 'A & B' is not assignable to type 'C'.
|
||||||
|
Type 'B' is not assignable to type 'C'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(29,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C | D'.
|
||||||
|
Type 'A & B' is not assignable to type 'C | D'.
|
||||||
|
Type 'A & B' is not assignable to type 'D'.
|
||||||
|
Type 'B' is not assignable to type 'D'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(31,1): error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'A & B' is not assignable to type 'C | D'.
|
||||||
|
Type 'A & B' is not assignable to type 'D'.
|
||||||
|
Type 'B' is not assignable to type 'D'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(32,1): error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'A' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'A' is not assignable to type 'C | D'.
|
||||||
|
Type 'A' is not assignable to type 'D'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(33,1): error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'C & D' is not assignable to type 'A | B'.
|
||||||
|
Type 'C & D' is not assignable to type 'B'.
|
||||||
|
Type 'D' is not assignable to type 'B'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(34,1): error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'C' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
Type 'C' is not assignable to type 'A | B'.
|
||||||
|
Type 'C' is not assignable to type 'B'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(35,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
|
||||||
|
Type '(A | B) & (C | D)' is not assignable to type 'A'.
|
||||||
|
Type 'C | D' is not assignable to type 'A'.
|
||||||
|
Type 'C' is not assignable to type 'A'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
|
||||||
|
Type '(A | B) & (C | D)' is not assignable to type 'C'.
|
||||||
|
Type 'C | D' is not assignable to type 'C'.
|
||||||
|
Type 'D' is not assignable to type 'C'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts (14 errors) ====
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
interface D { d: string }
|
||||||
|
|
||||||
|
var a: A;
|
||||||
|
var b: B;
|
||||||
|
var c: C;
|
||||||
|
var d: D;
|
||||||
|
var anb: A & B;
|
||||||
|
var aob: A | B;
|
||||||
|
var cnd: C & D;
|
||||||
|
var cod: C | D;
|
||||||
|
var x: A & B | C & D;
|
||||||
|
var y: (A | B) & (C | D);
|
||||||
|
|
||||||
|
a = anb; // Ok
|
||||||
|
b = anb; // Ok
|
||||||
|
anb = a;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'A & B'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||||
|
anb = b;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type 'B' is not assignable to type 'A & B'.
|
||||||
|
!!! error TS2322: Type 'B' is not assignable to type 'A'.
|
||||||
|
!!! error TS2322: Property 'a' is missing in type 'B'.
|
||||||
|
|
||||||
|
x = anb; // Ok
|
||||||
|
x = aob;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'A | B' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'C & D'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'C'.
|
||||||
|
x = cnd; // Ok
|
||||||
|
x = cod;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'C | D' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type '(A & B) | (C & D)'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type 'C & D'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type 'D'.
|
||||||
|
anb = x;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A & B'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'A & B'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'A'.
|
||||||
|
!!! error TS2322: Type 'D' is not assignable to type 'A'.
|
||||||
|
aob = x;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A | B'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'A | B'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'B'.
|
||||||
|
!!! error TS2322: Type 'D' is not assignable to type 'B'.
|
||||||
|
cnd = x;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C & D'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'C & D'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'C'.
|
||||||
|
!!! error TS2322: Type 'B' is not assignable to type 'C'.
|
||||||
|
cod = x;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C | D'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'C | D'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'D'.
|
||||||
|
!!! error TS2322: Type 'B' is not assignable to type 'D'.
|
||||||
|
|
||||||
|
y = anb;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'C | D'.
|
||||||
|
!!! error TS2322: Type 'A & B' is not assignable to type 'D'.
|
||||||
|
!!! error TS2322: Type 'B' is not assignable to type 'D'.
|
||||||
|
y = aob;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'C | D'.
|
||||||
|
!!! error TS2322: Type 'A' is not assignable to type 'D'.
|
||||||
|
y = cnd;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'A | B'.
|
||||||
|
!!! error TS2322: Type 'C & D' is not assignable to type 'B'.
|
||||||
|
!!! error TS2322: Type 'D' is not assignable to type 'B'.
|
||||||
|
y = cod;
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type '(A | B) & (C | D)'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type 'A | B'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type 'B'.
|
||||||
|
anb = y;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
|
||||||
|
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A'.
|
||||||
|
!!! error TS2322: Type 'C | D' is not assignable to type 'A'.
|
||||||
|
!!! error TS2322: Type 'C' is not assignable to type 'A'.
|
||||||
|
aob = y; // Ok
|
||||||
|
cnd = y;
|
||||||
|
~~~
|
||||||
|
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
|
||||||
|
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C'.
|
||||||
|
!!! error TS2322: Type 'C | D' is not assignable to type 'C'.
|
||||||
|
!!! error TS2322: Type 'D' is not assignable to type 'C'.
|
||||||
|
cod = y; // Ok
|
||||||
|
|
72
tests/baselines/reference/intersectionAndUnionTypes.js
Normal file
72
tests/baselines/reference/intersectionAndUnionTypes.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//// [intersectionAndUnionTypes.ts]
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
interface D { d: string }
|
||||||
|
|
||||||
|
var a: A;
|
||||||
|
var b: B;
|
||||||
|
var c: C;
|
||||||
|
var d: D;
|
||||||
|
var anb: A & B;
|
||||||
|
var aob: A | B;
|
||||||
|
var cnd: C & D;
|
||||||
|
var cod: C | D;
|
||||||
|
var x: A & B | C & D;
|
||||||
|
var y: (A | B) & (C | D);
|
||||||
|
|
||||||
|
a = anb; // Ok
|
||||||
|
b = anb; // Ok
|
||||||
|
anb = a;
|
||||||
|
anb = b;
|
||||||
|
|
||||||
|
x = anb; // Ok
|
||||||
|
x = aob;
|
||||||
|
x = cnd; // Ok
|
||||||
|
x = cod;
|
||||||
|
anb = x;
|
||||||
|
aob = x;
|
||||||
|
cnd = x;
|
||||||
|
cod = x;
|
||||||
|
|
||||||
|
y = anb;
|
||||||
|
y = aob;
|
||||||
|
y = cnd;
|
||||||
|
y = cod;
|
||||||
|
anb = y;
|
||||||
|
aob = y; // Ok
|
||||||
|
cnd = y;
|
||||||
|
cod = y; // Ok
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionAndUnionTypes.js]
|
||||||
|
var a;
|
||||||
|
var b;
|
||||||
|
var c;
|
||||||
|
var d;
|
||||||
|
var anb;
|
||||||
|
var aob;
|
||||||
|
var cnd;
|
||||||
|
var cod;
|
||||||
|
var x;
|
||||||
|
var y;
|
||||||
|
a = anb; // Ok
|
||||||
|
b = anb; // Ok
|
||||||
|
anb = a;
|
||||||
|
anb = b;
|
||||||
|
x = anb; // Ok
|
||||||
|
x = aob;
|
||||||
|
x = cnd; // Ok
|
||||||
|
x = cod;
|
||||||
|
anb = x;
|
||||||
|
aob = x;
|
||||||
|
cnd = x;
|
||||||
|
cod = x;
|
||||||
|
y = anb;
|
||||||
|
y = aob;
|
||||||
|
y = cnd;
|
||||||
|
y = cod;
|
||||||
|
anb = y;
|
||||||
|
aob = y; // Ok
|
||||||
|
cnd = y;
|
||||||
|
cod = y; // Ok
|
|
@ -0,0 +1,45 @@
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeAssignment.ts(8,1): error TS2322: Type '{ a: string; }' is not assignable to type '{ a: string; b: string; }'.
|
||||||
|
Property 'b' is missing in type '{ a: string; }'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeAssignment.ts(9,1): error TS2322: Type '{ a: string; }' is not assignable to type '{ a: string; } & { b: string; }'.
|
||||||
|
Type '{ a: string; }' is not assignable to type '{ b: string; }'.
|
||||||
|
Property 'b' is missing in type '{ a: string; }'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeAssignment.ts(13,1): error TS2322: Type '{ b: string; }' is not assignable to type '{ a: string; b: string; }'.
|
||||||
|
Property 'a' is missing in type '{ b: string; }'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeAssignment.ts(14,1): error TS2322: Type '{ b: string; }' is not assignable to type '{ a: string; } & { b: string; }'.
|
||||||
|
Type '{ b: string; }' is not assignable to type '{ a: string; }'.
|
||||||
|
Property 'a' is missing in type '{ b: string; }'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/types/intersection/intersectionTypeAssignment.ts (4 errors) ====
|
||||||
|
var a: { a: string };
|
||||||
|
var b: { b: string };
|
||||||
|
var x: { a: string, b: string };
|
||||||
|
var y: { a: string } & { b: string };
|
||||||
|
|
||||||
|
a = x;
|
||||||
|
a = y;
|
||||||
|
x = a; // Error
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type '{ a: string; }' is not assignable to type '{ a: string; b: string; }'.
|
||||||
|
!!! error TS2322: Property 'b' is missing in type '{ a: string; }'.
|
||||||
|
y = a; // Error
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type '{ a: string; }' is not assignable to type '{ a: string; } & { b: string; }'.
|
||||||
|
!!! error TS2322: Type '{ a: string; }' is not assignable to type '{ b: string; }'.
|
||||||
|
!!! error TS2322: Property 'b' is missing in type '{ a: string; }'.
|
||||||
|
|
||||||
|
b = x;
|
||||||
|
b = y;
|
||||||
|
x = b; // Error
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: string; b: string; }'.
|
||||||
|
!!! error TS2322: Property 'a' is missing in type '{ b: string; }'.
|
||||||
|
y = b; // Error
|
||||||
|
~
|
||||||
|
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: string; } & { b: string; }'.
|
||||||
|
!!! error TS2322: Type '{ b: string; }' is not assignable to type '{ a: string; }'.
|
||||||
|
!!! error TS2322: Property 'a' is missing in type '{ b: string; }'.
|
||||||
|
|
||||||
|
x = y;
|
||||||
|
y = x;
|
||||||
|
|
35
tests/baselines/reference/intersectionTypeAssignment.js
Normal file
35
tests/baselines/reference/intersectionTypeAssignment.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//// [intersectionTypeAssignment.ts]
|
||||||
|
var a: { a: string };
|
||||||
|
var b: { b: string };
|
||||||
|
var x: { a: string, b: string };
|
||||||
|
var y: { a: string } & { b: string };
|
||||||
|
|
||||||
|
a = x;
|
||||||
|
a = y;
|
||||||
|
x = a; // Error
|
||||||
|
y = a; // Error
|
||||||
|
|
||||||
|
b = x;
|
||||||
|
b = y;
|
||||||
|
x = b; // Error
|
||||||
|
y = b; // Error
|
||||||
|
|
||||||
|
x = y;
|
||||||
|
y = x;
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionTypeAssignment.js]
|
||||||
|
var a;
|
||||||
|
var b;
|
||||||
|
var x;
|
||||||
|
var y;
|
||||||
|
a = x;
|
||||||
|
a = y;
|
||||||
|
x = a; // Error
|
||||||
|
y = a; // Error
|
||||||
|
b = x;
|
||||||
|
b = y;
|
||||||
|
x = b; // Error
|
||||||
|
y = b; // Error
|
||||||
|
x = y;
|
||||||
|
y = x;
|
31
tests/baselines/reference/intersectionTypeEquivalence.js
Normal file
31
tests/baselines/reference/intersectionTypeEquivalence.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//// [intersectionTypeEquivalence.ts]
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
|
||||||
|
// A & B is equivalent to B & A.
|
||||||
|
var y: A & B;
|
||||||
|
var y : B & A;
|
||||||
|
|
||||||
|
// AB & C is equivalent to A & BC, where AB is A & B and BC is B & C.
|
||||||
|
var z : A & B & C;
|
||||||
|
var z : (A & B) & C;
|
||||||
|
var z : A & (B & C);
|
||||||
|
var ab : A & B;
|
||||||
|
var bc : B & C;
|
||||||
|
var z1: typeof ab & C;
|
||||||
|
var z1: A & typeof bc;
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionTypeEquivalence.js]
|
||||||
|
// A & B is equivalent to B & A.
|
||||||
|
var y;
|
||||||
|
var y;
|
||||||
|
// AB & C is equivalent to A & BC, where AB is A & B and BC is B & C.
|
||||||
|
var z;
|
||||||
|
var z;
|
||||||
|
var z;
|
||||||
|
var ab;
|
||||||
|
var bc;
|
||||||
|
var z1;
|
||||||
|
var z1;
|
|
@ -0,0 +1,63 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeEquivalence.ts ===
|
||||||
|
interface A { a: string }
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>a : Symbol(a, Decl(intersectionTypeEquivalence.ts, 0, 13))
|
||||||
|
|
||||||
|
interface B { b: string }
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>b : Symbol(b, Decl(intersectionTypeEquivalence.ts, 1, 13))
|
||||||
|
|
||||||
|
interface C { c: string }
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
>c : Symbol(c, Decl(intersectionTypeEquivalence.ts, 2, 13))
|
||||||
|
|
||||||
|
// A & B is equivalent to B & A.
|
||||||
|
var y: A & B;
|
||||||
|
>y : Symbol(y, Decl(intersectionTypeEquivalence.ts, 5, 3), Decl(intersectionTypeEquivalence.ts, 6, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
|
||||||
|
var y : B & A;
|
||||||
|
>y : Symbol(y, Decl(intersectionTypeEquivalence.ts, 5, 3), Decl(intersectionTypeEquivalence.ts, 6, 3))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
|
||||||
|
// AB & C is equivalent to A & BC, where AB is A & B and BC is B & C.
|
||||||
|
var z : A & B & C;
|
||||||
|
>z : Symbol(z, Decl(intersectionTypeEquivalence.ts, 9, 3), Decl(intersectionTypeEquivalence.ts, 10, 3), Decl(intersectionTypeEquivalence.ts, 11, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
|
||||||
|
var z : (A & B) & C;
|
||||||
|
>z : Symbol(z, Decl(intersectionTypeEquivalence.ts, 9, 3), Decl(intersectionTypeEquivalence.ts, 10, 3), Decl(intersectionTypeEquivalence.ts, 11, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
|
||||||
|
var z : A & (B & C);
|
||||||
|
>z : Symbol(z, Decl(intersectionTypeEquivalence.ts, 9, 3), Decl(intersectionTypeEquivalence.ts, 10, 3), Decl(intersectionTypeEquivalence.ts, 11, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
|
||||||
|
var ab : A & B;
|
||||||
|
>ab : Symbol(ab, Decl(intersectionTypeEquivalence.ts, 12, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
|
||||||
|
var bc : B & C;
|
||||||
|
>bc : Symbol(bc, Decl(intersectionTypeEquivalence.ts, 13, 3))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeEquivalence.ts, 0, 25))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
|
||||||
|
var z1: typeof ab & C;
|
||||||
|
>z1 : Symbol(z1, Decl(intersectionTypeEquivalence.ts, 14, 3), Decl(intersectionTypeEquivalence.ts, 15, 3))
|
||||||
|
>ab : Symbol(ab, Decl(intersectionTypeEquivalence.ts, 12, 3))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeEquivalence.ts, 1, 25))
|
||||||
|
|
||||||
|
var z1: A & typeof bc;
|
||||||
|
>z1 : Symbol(z1, Decl(intersectionTypeEquivalence.ts, 14, 3), Decl(intersectionTypeEquivalence.ts, 15, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeEquivalence.ts, 0, 0))
|
||||||
|
>bc : Symbol(bc, Decl(intersectionTypeEquivalence.ts, 13, 3))
|
||||||
|
|
63
tests/baselines/reference/intersectionTypeEquivalence.types
Normal file
63
tests/baselines/reference/intersectionTypeEquivalence.types
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeEquivalence.ts ===
|
||||||
|
interface A { a: string }
|
||||||
|
>A : A
|
||||||
|
>a : string
|
||||||
|
|
||||||
|
interface B { b: string }
|
||||||
|
>B : B
|
||||||
|
>b : string
|
||||||
|
|
||||||
|
interface C { c: string }
|
||||||
|
>C : C
|
||||||
|
>c : string
|
||||||
|
|
||||||
|
// A & B is equivalent to B & A.
|
||||||
|
var y: A & B;
|
||||||
|
>y : A & B
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
|
||||||
|
var y : B & A;
|
||||||
|
>y : A & B
|
||||||
|
>B : B
|
||||||
|
>A : A
|
||||||
|
|
||||||
|
// AB & C is equivalent to A & BC, where AB is A & B and BC is B & C.
|
||||||
|
var z : A & B & C;
|
||||||
|
>z : A & B & C
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var z : (A & B) & C;
|
||||||
|
>z : A & B & C
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var z : A & (B & C);
|
||||||
|
>z : A & B & C
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var ab : A & B;
|
||||||
|
>ab : A & B
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
|
||||||
|
var bc : B & C;
|
||||||
|
>bc : B & C
|
||||||
|
>B : B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var z1: typeof ab & C;
|
||||||
|
>z1 : A & B & C
|
||||||
|
>ab : A & B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var z1: A & typeof bc;
|
||||||
|
>z1 : A & B & C
|
||||||
|
>A : A
|
||||||
|
>bc : B & C
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeInference.ts(5,5): error TS2322: Type 'T' is not assignable to type 'T & U'.
|
||||||
|
Type 'T' is not assignable to type 'U'.
|
||||||
|
tests/cases/conformance/types/intersection/intersectionTypeInference.ts(6,5): error TS2322: Type 'U' is not assignable to type 'T & U'.
|
||||||
|
Type 'U' is not assignable to type 'T'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/types/intersection/intersectionTypeInference.ts (2 errors) ====
|
||||||
|
function extend<T, U>(obj1: T, obj2: U): T & U {
|
||||||
|
var result: T & U;
|
||||||
|
obj1 = result;
|
||||||
|
obj2 = result;
|
||||||
|
result = obj1; // Error
|
||||||
|
~~~~~~
|
||||||
|
!!! error TS2322: Type 'T' is not assignable to type 'T & U'.
|
||||||
|
!!! error TS2322: Type 'T' is not assignable to type 'U'.
|
||||||
|
result = obj2; // Error
|
||||||
|
~~~~~~
|
||||||
|
!!! error TS2322: Type 'U' is not assignable to type 'T & U'.
|
||||||
|
!!! error TS2322: Type 'U' is not assignable to type 'T'.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var x = extend({ a: "hello" }, { b: 42 });
|
||||||
|
var s = x.a;
|
||||||
|
var n = x.b;
|
||||||
|
|
||||||
|
interface A<T> {
|
||||||
|
a: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B<U> {
|
||||||
|
b: U;
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo<T, U>(obj: A<T> & B<U>): T | U {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var z = foo({ a: "hello", b: 42 });
|
||||||
|
var z: string | number;
|
||||||
|
|
47
tests/baselines/reference/intersectionTypeInference.js
Normal file
47
tests/baselines/reference/intersectionTypeInference.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//// [intersectionTypeInference.ts]
|
||||||
|
function extend<T, U>(obj1: T, obj2: U): T & U {
|
||||||
|
var result: T & U;
|
||||||
|
obj1 = result;
|
||||||
|
obj2 = result;
|
||||||
|
result = obj1; // Error
|
||||||
|
result = obj2; // Error
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var x = extend({ a: "hello" }, { b: 42 });
|
||||||
|
var s = x.a;
|
||||||
|
var n = x.b;
|
||||||
|
|
||||||
|
interface A<T> {
|
||||||
|
a: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B<U> {
|
||||||
|
b: U;
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo<T, U>(obj: A<T> & B<U>): T | U {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var z = foo({ a: "hello", b: 42 });
|
||||||
|
var z: string | number;
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionTypeInference.js]
|
||||||
|
function extend(obj1, obj2) {
|
||||||
|
var result;
|
||||||
|
obj1 = result;
|
||||||
|
obj2 = result;
|
||||||
|
result = obj1; // Error
|
||||||
|
result = obj2; // Error
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
var x = extend({ a: "hello" }, { b: 42 });
|
||||||
|
var s = x.a;
|
||||||
|
var n = x.b;
|
||||||
|
function foo(obj) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
var z = foo({ a: "hello", b: 42 });
|
||||||
|
var z;
|
44
tests/baselines/reference/intersectionTypeMembers.js
Normal file
44
tests/baselines/reference/intersectionTypeMembers.js
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
//// [intersectionTypeMembers.ts]
|
||||||
|
// An intersection type has those members that are present in any of its constituent types,
|
||||||
|
// with types that are intersections of the respective members in the constituent types
|
||||||
|
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
|
||||||
|
var abc: A & B & C;
|
||||||
|
abc.a = "hello";
|
||||||
|
abc.b = "hello";
|
||||||
|
abc.c = "hello";
|
||||||
|
|
||||||
|
interface X { x: A }
|
||||||
|
interface Y { x: B }
|
||||||
|
interface Z { x: C }
|
||||||
|
|
||||||
|
var xyz: X & Y & Z;
|
||||||
|
xyz.x.a = "hello";
|
||||||
|
xyz.x.b = "hello";
|
||||||
|
xyz.x.c = "hello";
|
||||||
|
|
||||||
|
type F1 = (x: string) => string;
|
||||||
|
type F2 = (x: number) => number;
|
||||||
|
|
||||||
|
var f: F1 & F2;
|
||||||
|
var s = f("hello");
|
||||||
|
var n = f(42);
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionTypeMembers.js]
|
||||||
|
// An intersection type has those members that are present in any of its constituent types,
|
||||||
|
// with types that are intersections of the respective members in the constituent types
|
||||||
|
var abc;
|
||||||
|
abc.a = "hello";
|
||||||
|
abc.b = "hello";
|
||||||
|
abc.c = "hello";
|
||||||
|
var xyz;
|
||||||
|
xyz.x.a = "hello";
|
||||||
|
xyz.x.b = "hello";
|
||||||
|
xyz.x.c = "hello";
|
||||||
|
var f;
|
||||||
|
var s = f("hello");
|
||||||
|
var n = f(42);
|
100
tests/baselines/reference/intersectionTypeMembers.symbols
Normal file
100
tests/baselines/reference/intersectionTypeMembers.symbols
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeMembers.ts ===
|
||||||
|
// An intersection type has those members that are present in any of its constituent types,
|
||||||
|
// with types that are intersections of the respective members in the constituent types
|
||||||
|
|
||||||
|
interface A { a: string }
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeMembers.ts, 0, 0))
|
||||||
|
>a : Symbol(a, Decl(intersectionTypeMembers.ts, 3, 13))
|
||||||
|
|
||||||
|
interface B { b: string }
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeMembers.ts, 3, 25))
|
||||||
|
>b : Symbol(b, Decl(intersectionTypeMembers.ts, 4, 13))
|
||||||
|
|
||||||
|
interface C { c: string }
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeMembers.ts, 4, 25))
|
||||||
|
>c : Symbol(c, Decl(intersectionTypeMembers.ts, 5, 13))
|
||||||
|
|
||||||
|
var abc: A & B & C;
|
||||||
|
>abc : Symbol(abc, Decl(intersectionTypeMembers.ts, 7, 3))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeMembers.ts, 0, 0))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeMembers.ts, 3, 25))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeMembers.ts, 4, 25))
|
||||||
|
|
||||||
|
abc.a = "hello";
|
||||||
|
>abc.a : Symbol(A.a, Decl(intersectionTypeMembers.ts, 3, 13))
|
||||||
|
>abc : Symbol(abc, Decl(intersectionTypeMembers.ts, 7, 3))
|
||||||
|
>a : Symbol(A.a, Decl(intersectionTypeMembers.ts, 3, 13))
|
||||||
|
|
||||||
|
abc.b = "hello";
|
||||||
|
>abc.b : Symbol(B.b, Decl(intersectionTypeMembers.ts, 4, 13))
|
||||||
|
>abc : Symbol(abc, Decl(intersectionTypeMembers.ts, 7, 3))
|
||||||
|
>b : Symbol(B.b, Decl(intersectionTypeMembers.ts, 4, 13))
|
||||||
|
|
||||||
|
abc.c = "hello";
|
||||||
|
>abc.c : Symbol(C.c, Decl(intersectionTypeMembers.ts, 5, 13))
|
||||||
|
>abc : Symbol(abc, Decl(intersectionTypeMembers.ts, 7, 3))
|
||||||
|
>c : Symbol(C.c, Decl(intersectionTypeMembers.ts, 5, 13))
|
||||||
|
|
||||||
|
interface X { x: A }
|
||||||
|
>X : Symbol(X, Decl(intersectionTypeMembers.ts, 10, 16))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13))
|
||||||
|
>A : Symbol(A, Decl(intersectionTypeMembers.ts, 0, 0))
|
||||||
|
|
||||||
|
interface Y { x: B }
|
||||||
|
>Y : Symbol(Y, Decl(intersectionTypeMembers.ts, 12, 20))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 13, 13))
|
||||||
|
>B : Symbol(B, Decl(intersectionTypeMembers.ts, 3, 25))
|
||||||
|
|
||||||
|
interface Z { x: C }
|
||||||
|
>Z : Symbol(Z, Decl(intersectionTypeMembers.ts, 13, 20))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>C : Symbol(C, Decl(intersectionTypeMembers.ts, 4, 25))
|
||||||
|
|
||||||
|
var xyz: X & Y & Z;
|
||||||
|
>xyz : Symbol(xyz, Decl(intersectionTypeMembers.ts, 16, 3))
|
||||||
|
>X : Symbol(X, Decl(intersectionTypeMembers.ts, 10, 16))
|
||||||
|
>Y : Symbol(Y, Decl(intersectionTypeMembers.ts, 12, 20))
|
||||||
|
>Z : Symbol(Z, Decl(intersectionTypeMembers.ts, 13, 20))
|
||||||
|
|
||||||
|
xyz.x.a = "hello";
|
||||||
|
>xyz.x.a : Symbol(A.a, Decl(intersectionTypeMembers.ts, 3, 13))
|
||||||
|
>xyz.x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>xyz : Symbol(xyz, Decl(intersectionTypeMembers.ts, 16, 3))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>a : Symbol(A.a, Decl(intersectionTypeMembers.ts, 3, 13))
|
||||||
|
|
||||||
|
xyz.x.b = "hello";
|
||||||
|
>xyz.x.b : Symbol(B.b, Decl(intersectionTypeMembers.ts, 4, 13))
|
||||||
|
>xyz.x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>xyz : Symbol(xyz, Decl(intersectionTypeMembers.ts, 16, 3))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>b : Symbol(B.b, Decl(intersectionTypeMembers.ts, 4, 13))
|
||||||
|
|
||||||
|
xyz.x.c = "hello";
|
||||||
|
>xyz.x.c : Symbol(C.c, Decl(intersectionTypeMembers.ts, 5, 13))
|
||||||
|
>xyz.x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>xyz : Symbol(xyz, Decl(intersectionTypeMembers.ts, 16, 3))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 12, 13), Decl(intersectionTypeMembers.ts, 13, 13), Decl(intersectionTypeMembers.ts, 14, 13))
|
||||||
|
>c : Symbol(C.c, Decl(intersectionTypeMembers.ts, 5, 13))
|
||||||
|
|
||||||
|
type F1 = (x: string) => string;
|
||||||
|
>F1 : Symbol(F1, Decl(intersectionTypeMembers.ts, 19, 18))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 21, 11))
|
||||||
|
|
||||||
|
type F2 = (x: number) => number;
|
||||||
|
>F2 : Symbol(F2, Decl(intersectionTypeMembers.ts, 21, 32))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeMembers.ts, 22, 11))
|
||||||
|
|
||||||
|
var f: F1 & F2;
|
||||||
|
>f : Symbol(f, Decl(intersectionTypeMembers.ts, 24, 3))
|
||||||
|
>F1 : Symbol(F1, Decl(intersectionTypeMembers.ts, 19, 18))
|
||||||
|
>F2 : Symbol(F2, Decl(intersectionTypeMembers.ts, 21, 32))
|
||||||
|
|
||||||
|
var s = f("hello");
|
||||||
|
>s : Symbol(s, Decl(intersectionTypeMembers.ts, 25, 3))
|
||||||
|
>f : Symbol(f, Decl(intersectionTypeMembers.ts, 24, 3))
|
||||||
|
|
||||||
|
var n = f(42);
|
||||||
|
>n : Symbol(n, Decl(intersectionTypeMembers.ts, 26, 3))
|
||||||
|
>f : Symbol(f, Decl(intersectionTypeMembers.ts, 24, 3))
|
||||||
|
|
116
tests/baselines/reference/intersectionTypeMembers.types
Normal file
116
tests/baselines/reference/intersectionTypeMembers.types
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeMembers.ts ===
|
||||||
|
// An intersection type has those members that are present in any of its constituent types,
|
||||||
|
// with types that are intersections of the respective members in the constituent types
|
||||||
|
|
||||||
|
interface A { a: string }
|
||||||
|
>A : A
|
||||||
|
>a : string
|
||||||
|
|
||||||
|
interface B { b: string }
|
||||||
|
>B : B
|
||||||
|
>b : string
|
||||||
|
|
||||||
|
interface C { c: string }
|
||||||
|
>C : C
|
||||||
|
>c : string
|
||||||
|
|
||||||
|
var abc: A & B & C;
|
||||||
|
>abc : A & B & C
|
||||||
|
>A : A
|
||||||
|
>B : B
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
abc.a = "hello";
|
||||||
|
>abc.a = "hello" : string
|
||||||
|
>abc.a : string
|
||||||
|
>abc : A & B & C
|
||||||
|
>a : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
abc.b = "hello";
|
||||||
|
>abc.b = "hello" : string
|
||||||
|
>abc.b : string
|
||||||
|
>abc : A & B & C
|
||||||
|
>b : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
abc.c = "hello";
|
||||||
|
>abc.c = "hello" : string
|
||||||
|
>abc.c : string
|
||||||
|
>abc : A & B & C
|
||||||
|
>c : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
interface X { x: A }
|
||||||
|
>X : X
|
||||||
|
>x : A
|
||||||
|
>A : A
|
||||||
|
|
||||||
|
interface Y { x: B }
|
||||||
|
>Y : Y
|
||||||
|
>x : B
|
||||||
|
>B : B
|
||||||
|
|
||||||
|
interface Z { x: C }
|
||||||
|
>Z : Z
|
||||||
|
>x : C
|
||||||
|
>C : C
|
||||||
|
|
||||||
|
var xyz: X & Y & Z;
|
||||||
|
>xyz : X & Y & Z
|
||||||
|
>X : X
|
||||||
|
>Y : Y
|
||||||
|
>Z : Z
|
||||||
|
|
||||||
|
xyz.x.a = "hello";
|
||||||
|
>xyz.x.a = "hello" : string
|
||||||
|
>xyz.x.a : string
|
||||||
|
>xyz.x : A & B & C
|
||||||
|
>xyz : X & Y & Z
|
||||||
|
>x : A & B & C
|
||||||
|
>a : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
xyz.x.b = "hello";
|
||||||
|
>xyz.x.b = "hello" : string
|
||||||
|
>xyz.x.b : string
|
||||||
|
>xyz.x : A & B & C
|
||||||
|
>xyz : X & Y & Z
|
||||||
|
>x : A & B & C
|
||||||
|
>b : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
xyz.x.c = "hello";
|
||||||
|
>xyz.x.c = "hello" : string
|
||||||
|
>xyz.x.c : string
|
||||||
|
>xyz.x : A & B & C
|
||||||
|
>xyz : X & Y & Z
|
||||||
|
>x : A & B & C
|
||||||
|
>c : string
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
type F1 = (x: string) => string;
|
||||||
|
>F1 : (x: string) => string
|
||||||
|
>x : string
|
||||||
|
|
||||||
|
type F2 = (x: number) => number;
|
||||||
|
>F2 : (x: number) => number
|
||||||
|
>x : number
|
||||||
|
|
||||||
|
var f: F1 & F2;
|
||||||
|
>f : ((x: string) => string) & ((x: number) => number)
|
||||||
|
>F1 : (x: string) => string
|
||||||
|
>F2 : (x: number) => number
|
||||||
|
|
||||||
|
var s = f("hello");
|
||||||
|
>s : string
|
||||||
|
>f("hello") : string
|
||||||
|
>f : ((x: string) => string) & ((x: number) => number)
|
||||||
|
>"hello" : string
|
||||||
|
|
||||||
|
var n = f(42);
|
||||||
|
>n : number
|
||||||
|
>f(42) : number
|
||||||
|
>f : ((x: string) => string) & ((x: number) => number)
|
||||||
|
>42 : number
|
||||||
|
|
26
tests/baselines/reference/intersectionTypeOverloading.js
Normal file
26
tests/baselines/reference/intersectionTypeOverloading.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//// [intersectionTypeOverloading.ts]
|
||||||
|
// Check that order is preserved in intersection types for purposes of
|
||||||
|
// overload resolution
|
||||||
|
|
||||||
|
type F = (s: string) => string;
|
||||||
|
type G = (x: any) => any;
|
||||||
|
|
||||||
|
var fg: F & G;
|
||||||
|
var gf: G & F;
|
||||||
|
|
||||||
|
var x = fg("abc");
|
||||||
|
var x: string;
|
||||||
|
|
||||||
|
var y = gf("abc");
|
||||||
|
var y: any;
|
||||||
|
|
||||||
|
|
||||||
|
//// [intersectionTypeOverloading.js]
|
||||||
|
// Check that order is preserved in intersection types for purposes of
|
||||||
|
// overload resolution
|
||||||
|
var fg;
|
||||||
|
var gf;
|
||||||
|
var x = fg("abc");
|
||||||
|
var x;
|
||||||
|
var y = gf("abc");
|
||||||
|
var y;
|
|
@ -0,0 +1,36 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeOverloading.ts ===
|
||||||
|
// Check that order is preserved in intersection types for purposes of
|
||||||
|
// overload resolution
|
||||||
|
|
||||||
|
type F = (s: string) => string;
|
||||||
|
>F : Symbol(F, Decl(intersectionTypeOverloading.ts, 0, 0))
|
||||||
|
>s : Symbol(s, Decl(intersectionTypeOverloading.ts, 3, 10))
|
||||||
|
|
||||||
|
type G = (x: any) => any;
|
||||||
|
>G : Symbol(G, Decl(intersectionTypeOverloading.ts, 3, 31))
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeOverloading.ts, 4, 10))
|
||||||
|
|
||||||
|
var fg: F & G;
|
||||||
|
>fg : Symbol(fg, Decl(intersectionTypeOverloading.ts, 6, 3))
|
||||||
|
>F : Symbol(F, Decl(intersectionTypeOverloading.ts, 0, 0))
|
||||||
|
>G : Symbol(G, Decl(intersectionTypeOverloading.ts, 3, 31))
|
||||||
|
|
||||||
|
var gf: G & F;
|
||||||
|
>gf : Symbol(gf, Decl(intersectionTypeOverloading.ts, 7, 3))
|
||||||
|
>G : Symbol(G, Decl(intersectionTypeOverloading.ts, 3, 31))
|
||||||
|
>F : Symbol(F, Decl(intersectionTypeOverloading.ts, 0, 0))
|
||||||
|
|
||||||
|
var x = fg("abc");
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeOverloading.ts, 9, 3), Decl(intersectionTypeOverloading.ts, 10, 3))
|
||||||
|
>fg : Symbol(fg, Decl(intersectionTypeOverloading.ts, 6, 3))
|
||||||
|
|
||||||
|
var x: string;
|
||||||
|
>x : Symbol(x, Decl(intersectionTypeOverloading.ts, 9, 3), Decl(intersectionTypeOverloading.ts, 10, 3))
|
||||||
|
|
||||||
|
var y = gf("abc");
|
||||||
|
>y : Symbol(y, Decl(intersectionTypeOverloading.ts, 12, 3), Decl(intersectionTypeOverloading.ts, 13, 3))
|
||||||
|
>gf : Symbol(gf, Decl(intersectionTypeOverloading.ts, 7, 3))
|
||||||
|
|
||||||
|
var y: any;
|
||||||
|
>y : Symbol(y, Decl(intersectionTypeOverloading.ts, 12, 3), Decl(intersectionTypeOverloading.ts, 13, 3))
|
||||||
|
|
40
tests/baselines/reference/intersectionTypeOverloading.types
Normal file
40
tests/baselines/reference/intersectionTypeOverloading.types
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
=== tests/cases/conformance/types/intersection/intersectionTypeOverloading.ts ===
|
||||||
|
// Check that order is preserved in intersection types for purposes of
|
||||||
|
// overload resolution
|
||||||
|
|
||||||
|
type F = (s: string) => string;
|
||||||
|
>F : (s: string) => string
|
||||||
|
>s : string
|
||||||
|
|
||||||
|
type G = (x: any) => any;
|
||||||
|
>G : (x: any) => any
|
||||||
|
>x : any
|
||||||
|
|
||||||
|
var fg: F & G;
|
||||||
|
>fg : ((s: string) => string) & ((x: any) => any)
|
||||||
|
>F : (s: string) => string
|
||||||
|
>G : (x: any) => any
|
||||||
|
|
||||||
|
var gf: G & F;
|
||||||
|
>gf : ((x: any) => any) & ((s: string) => string)
|
||||||
|
>G : (x: any) => any
|
||||||
|
>F : (s: string) => string
|
||||||
|
|
||||||
|
var x = fg("abc");
|
||||||
|
>x : string
|
||||||
|
>fg("abc") : string
|
||||||
|
>fg : ((s: string) => string) & ((x: any) => any)
|
||||||
|
>"abc" : string
|
||||||
|
|
||||||
|
var x: string;
|
||||||
|
>x : string
|
||||||
|
|
||||||
|
var y = gf("abc");
|
||||||
|
>y : any
|
||||||
|
>gf("abc") : any
|
||||||
|
>gf : ((x: any) => any) & ((s: string) => string)
|
||||||
|
>"abc" : string
|
||||||
|
|
||||||
|
var y: any;
|
||||||
|
>y : any
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
tests/cases/conformance/types/intersection/recursiveIntersectionTypes.ts(19,1): error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product & { next: Product & any; }'.
|
||||||
|
Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product'.
|
||||||
|
Type '{ next: Entity & any; }' is not assignable to type 'Product'.
|
||||||
|
Property 'price' is missing in type '{ next: Entity & any; }'.
|
||||||
|
|
||||||
|
|
||||||
|
==== tests/cases/conformance/types/intersection/recursiveIntersectionTypes.ts (1 errors) ====
|
||||||
|
type LinkedList<T> = T & { next: LinkedList<T> };
|
||||||
|
|
||||||
|
interface Entity {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Product extends Entity {
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityList: LinkedList<Entity>;
|
||||||
|
var s = entityList.name;
|
||||||
|
var s = entityList.next.name;
|
||||||
|
var s = entityList.next.next.name;
|
||||||
|
var s = entityList.next.next.next.name;
|
||||||
|
|
||||||
|
var productList: LinkedList<Product>;
|
||||||
|
entityList = productList;
|
||||||
|
productList = entityList; // Error
|
||||||
|
~~~~~~~~~~~
|
||||||
|
!!! error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product & { next: Product & any; }'.
|
||||||
|
!!! error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product'.
|
||||||
|
!!! error TS2322: Type '{ next: Entity & any; }' is not assignable to type 'Product'.
|
||||||
|
!!! error TS2322: Property 'price' is missing in type '{ next: Entity & any; }'.
|
||||||
|
|
31
tests/baselines/reference/recursiveIntersectionTypes.js
Normal file
31
tests/baselines/reference/recursiveIntersectionTypes.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
//// [recursiveIntersectionTypes.ts]
|
||||||
|
type LinkedList<T> = T & { next: LinkedList<T> };
|
||||||
|
|
||||||
|
interface Entity {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Product extends Entity {
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityList: LinkedList<Entity>;
|
||||||
|
var s = entityList.name;
|
||||||
|
var s = entityList.next.name;
|
||||||
|
var s = entityList.next.next.name;
|
||||||
|
var s = entityList.next.next.next.name;
|
||||||
|
|
||||||
|
var productList: LinkedList<Product>;
|
||||||
|
entityList = productList;
|
||||||
|
productList = entityList; // Error
|
||||||
|
|
||||||
|
|
||||||
|
//// [recursiveIntersectionTypes.js]
|
||||||
|
var entityList;
|
||||||
|
var s = entityList.name;
|
||||||
|
var s = entityList.next.name;
|
||||||
|
var s = entityList.next.next.name;
|
||||||
|
var s = entityList.next.next.next.name;
|
||||||
|
var productList;
|
||||||
|
entityList = productList;
|
||||||
|
productList = entityList; // Error
|
|
@ -33,9 +33,9 @@ function f<T extends Cat | Dog>(a: T) {
|
||||||
>T : Symbol(T, Decl(typeParameterExtendingUnion1.ts, 8, 11))
|
>T : Symbol(T, Decl(typeParameterExtendingUnion1.ts, 8, 11))
|
||||||
|
|
||||||
a.run();
|
a.run();
|
||||||
>a.run : Symbol(run, Decl(typeParameterExtendingUnion1.ts, 0, 14), Decl(typeParameterExtendingUnion1.ts, 0, 14))
|
>a.run : Symbol(Animal.run, Decl(typeParameterExtendingUnion1.ts, 0, 14))
|
||||||
>a : Symbol(a, Decl(typeParameterExtendingUnion1.ts, 8, 32))
|
>a : Symbol(a, Decl(typeParameterExtendingUnion1.ts, 8, 32))
|
||||||
>run : Symbol(run, Decl(typeParameterExtendingUnion1.ts, 0, 14), Decl(typeParameterExtendingUnion1.ts, 0, 14))
|
>run : Symbol(Animal.run, Decl(typeParameterExtendingUnion1.ts, 0, 14))
|
||||||
|
|
||||||
run(a);
|
run(a);
|
||||||
>run : Symbol(run, Decl(typeParameterExtendingUnion1.ts, 2, 33))
|
>run : Symbol(run, Decl(typeParameterExtendingUnion1.ts, 2, 33))
|
||||||
|
|
|
@ -20,9 +20,9 @@ function run(a: Cat | Dog) {
|
||||||
>Dog : Symbol(Dog, Decl(typeParameterExtendingUnion2.ts, 1, 33))
|
>Dog : Symbol(Dog, Decl(typeParameterExtendingUnion2.ts, 1, 33))
|
||||||
|
|
||||||
a.run();
|
a.run();
|
||||||
>a.run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 0, 14), Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
>a.run : Symbol(Animal.run, Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
||||||
>a : Symbol(a, Decl(typeParameterExtendingUnion2.ts, 4, 13))
|
>a : Symbol(a, Decl(typeParameterExtendingUnion2.ts, 4, 13))
|
||||||
>run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 0, 14), Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
>run : Symbol(Animal.run, Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
||||||
}
|
}
|
||||||
|
|
||||||
function f<T extends Cat | Dog>(a: T) {
|
function f<T extends Cat | Dog>(a: T) {
|
||||||
|
@ -34,9 +34,9 @@ function f<T extends Cat | Dog>(a: T) {
|
||||||
>T : Symbol(T, Decl(typeParameterExtendingUnion2.ts, 8, 11))
|
>T : Symbol(T, Decl(typeParameterExtendingUnion2.ts, 8, 11))
|
||||||
|
|
||||||
a.run();
|
a.run();
|
||||||
>a.run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 0, 14), Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
>a.run : Symbol(Animal.run, Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
||||||
>a : Symbol(a, Decl(typeParameterExtendingUnion2.ts, 8, 32))
|
>a : Symbol(a, Decl(typeParameterExtendingUnion2.ts, 8, 32))
|
||||||
>run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 0, 14), Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
>run : Symbol(Animal.run, Decl(typeParameterExtendingUnion2.ts, 0, 14))
|
||||||
|
|
||||||
run(a);
|
run(a);
|
||||||
>run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 2, 33))
|
>run : Symbol(run, Decl(typeParameterExtendingUnion2.ts, 2, 33))
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
var x: { a: (s: string) => string } & { b: (n: number) => number };
|
||||||
|
x = {
|
||||||
|
a: s => s,
|
||||||
|
b: n => n
|
||||||
|
};
|
|
@ -0,0 +1,38 @@
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
interface D { d: string }
|
||||||
|
|
||||||
|
var a: A;
|
||||||
|
var b: B;
|
||||||
|
var c: C;
|
||||||
|
var d: D;
|
||||||
|
var anb: A & B;
|
||||||
|
var aob: A | B;
|
||||||
|
var cnd: C & D;
|
||||||
|
var cod: C | D;
|
||||||
|
var x: A & B | C & D;
|
||||||
|
var y: (A | B) & (C | D);
|
||||||
|
|
||||||
|
a = anb; // Ok
|
||||||
|
b = anb; // Ok
|
||||||
|
anb = a;
|
||||||
|
anb = b;
|
||||||
|
|
||||||
|
x = anb; // Ok
|
||||||
|
x = aob;
|
||||||
|
x = cnd; // Ok
|
||||||
|
x = cod;
|
||||||
|
anb = x;
|
||||||
|
aob = x;
|
||||||
|
cnd = x;
|
||||||
|
cod = x;
|
||||||
|
|
||||||
|
y = anb;
|
||||||
|
y = aob;
|
||||||
|
y = cnd;
|
||||||
|
y = cod;
|
||||||
|
anb = y;
|
||||||
|
aob = y; // Ok
|
||||||
|
cnd = y;
|
||||||
|
cod = y; // Ok
|
|
@ -0,0 +1,17 @@
|
||||||
|
var a: { a: string };
|
||||||
|
var b: { b: string };
|
||||||
|
var x: { a: string, b: string };
|
||||||
|
var y: { a: string } & { b: string };
|
||||||
|
|
||||||
|
a = x;
|
||||||
|
a = y;
|
||||||
|
x = a; // Error
|
||||||
|
y = a; // Error
|
||||||
|
|
||||||
|
b = x;
|
||||||
|
b = y;
|
||||||
|
x = b; // Error
|
||||||
|
y = b; // Error
|
||||||
|
|
||||||
|
x = y;
|
||||||
|
y = x;
|
|
@ -0,0 +1,16 @@
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
|
||||||
|
// A & B is equivalent to B & A.
|
||||||
|
var y: A & B;
|
||||||
|
var y : B & A;
|
||||||
|
|
||||||
|
// AB & C is equivalent to A & BC, where AB is A & B and BC is B & C.
|
||||||
|
var z : A & B & C;
|
||||||
|
var z : (A & B) & C;
|
||||||
|
var z : A & (B & C);
|
||||||
|
var ab : A & B;
|
||||||
|
var bc : B & C;
|
||||||
|
var z1: typeof ab & C;
|
||||||
|
var z1: A & typeof bc;
|
|
@ -0,0 +1,27 @@
|
||||||
|
function extend<T, U>(obj1: T, obj2: U): T & U {
|
||||||
|
var result: T & U;
|
||||||
|
obj1 = result;
|
||||||
|
obj2 = result;
|
||||||
|
result = obj1; // Error
|
||||||
|
result = obj2; // Error
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var x = extend({ a: "hello" }, { b: 42 });
|
||||||
|
var s = x.a;
|
||||||
|
var n = x.b;
|
||||||
|
|
||||||
|
interface A<T> {
|
||||||
|
a: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface B<U> {
|
||||||
|
b: U;
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo<T, U>(obj: A<T> & B<U>): T | U {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var z = foo({ a: "hello", b: 42 });
|
||||||
|
var z: string | number;
|
|
@ -0,0 +1,27 @@
|
||||||
|
// An intersection type has those members that are present in any of its constituent types,
|
||||||
|
// with types that are intersections of the respective members in the constituent types
|
||||||
|
|
||||||
|
interface A { a: string }
|
||||||
|
interface B { b: string }
|
||||||
|
interface C { c: string }
|
||||||
|
|
||||||
|
var abc: A & B & C;
|
||||||
|
abc.a = "hello";
|
||||||
|
abc.b = "hello";
|
||||||
|
abc.c = "hello";
|
||||||
|
|
||||||
|
interface X { x: A }
|
||||||
|
interface Y { x: B }
|
||||||
|
interface Z { x: C }
|
||||||
|
|
||||||
|
var xyz: X & Y & Z;
|
||||||
|
xyz.x.a = "hello";
|
||||||
|
xyz.x.b = "hello";
|
||||||
|
xyz.x.c = "hello";
|
||||||
|
|
||||||
|
type F1 = (x: string) => string;
|
||||||
|
type F2 = (x: number) => number;
|
||||||
|
|
||||||
|
var f: F1 & F2;
|
||||||
|
var s = f("hello");
|
||||||
|
var n = f(42);
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Check that order is preserved in intersection types for purposes of
|
||||||
|
// overload resolution
|
||||||
|
|
||||||
|
type F = (s: string) => string;
|
||||||
|
type G = (x: any) => any;
|
||||||
|
|
||||||
|
var fg: F & G;
|
||||||
|
var gf: G & F;
|
||||||
|
|
||||||
|
var x = fg("abc");
|
||||||
|
var x: string;
|
||||||
|
|
||||||
|
var y = gf("abc");
|
||||||
|
var y: any;
|
|
@ -0,0 +1,19 @@
|
||||||
|
type LinkedList<T> = T & { next: LinkedList<T> };
|
||||||
|
|
||||||
|
interface Entity {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Product extends Entity {
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entityList: LinkedList<Entity>;
|
||||||
|
var s = entityList.name;
|
||||||
|
var s = entityList.next.name;
|
||||||
|
var s = entityList.next.next.name;
|
||||||
|
var s = entityList.next.next.next.name;
|
||||||
|
|
||||||
|
var productList: LinkedList<Product>;
|
||||||
|
entityList = productList;
|
||||||
|
productList = entityList; // Error
|
Loading…
Reference in a new issue