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 unionTypes: Map<UnionType> = {};
|
||||
let intersectionTypes: Map<IntersectionType> = {};
|
||||
let stringLiteralTypes: Map<StringLiteralType> = {};
|
||||
let emitExtends = false;
|
||||
let emitDecorate = false;
|
||||
|
@ -1575,8 +1576,8 @@ namespace ts {
|
|||
else if (type.flags & TypeFlags.Tuple) {
|
||||
writeTupleType(<TupleType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Union) {
|
||||
writeUnionType(<UnionType>type, flags);
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, flags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Anonymous) {
|
||||
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++) {
|
||||
if (i > 0) {
|
||||
if (union) {
|
||||
if (delimiter !== SyntaxKind.CommaToken) {
|
||||
writeSpace(writer);
|
||||
}
|
||||
writePunctuation(writer, union ? SyntaxKind.BarToken : SyntaxKind.CommaToken);
|
||||
writePunctuation(writer, delimiter);
|
||||
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) {
|
||||
writePunctuation(writer, SyntaxKind.OpenBracketToken);
|
||||
writeTypeList(type.elementTypes, /*union*/ false);
|
||||
writeTypeList(type.elementTypes, SyntaxKind.CommaToken);
|
||||
writePunctuation(writer, SyntaxKind.CloseBracketToken);
|
||||
}
|
||||
|
||||
function writeUnionType(type: UnionType, flags: TypeFormatFlags) {
|
||||
function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
writeTypeList(type.types, /*union*/ true);
|
||||
writeTypeList(type.types, type.flags & TypeFlags.Union ? SyntaxKind.BarToken : SyntaxKind.AmpersandToken);
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
|
@ -1747,7 +1748,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(type);
|
||||
let resolved = resolveStructuredTypeMembers(type);
|
||||
if (!resolved.properties.length && !resolved.stringIndexType && !resolved.numberIndexType) {
|
||||
if (!resolved.callSignatures.length && !resolved.constructSignatures.length) {
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
|
@ -2082,6 +2083,7 @@ namespace ts {
|
|||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return isDeclarationVisible(<Declaration>node.parent);
|
||||
|
||||
|
@ -2704,7 +2706,7 @@ namespace ts {
|
|||
if (baseConstructorType.flags & TypeFlags.ObjectType) {
|
||||
// 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.
|
||||
resolveObjectOrUnionTypeMembers(baseConstructorType);
|
||||
resolveStructuredTypeMembers(baseConstructorType);
|
||||
}
|
||||
if (!popTypeResolution()) {
|
||||
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) {
|
||||
let arrayType = resolveObjectOrUnionTypeMembers(createArrayType(getUnionType(type.elementTypes)));
|
||||
let arrayType = resolveStructuredTypeMembers(createArrayType(getUnionType(type.elementTypes)));
|
||||
let members = createTupleTypeMemberSymbols(type.elementTypes);
|
||||
addInheritedMembers(members, arrayType.properties);
|
||||
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
||||
|
@ -3100,6 +3102,26 @@ namespace ts {
|
|||
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) {
|
||||
let symbol = type.symbol;
|
||||
let members: SymbolTable;
|
||||
|
@ -3144,7 +3166,7 @@ namespace ts {
|
|||
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||
}
|
||||
|
||||
function resolveObjectOrUnionTypeMembers(type: ObjectType): ResolvedType {
|
||||
function resolveStructuredTypeMembers(type: ObjectType): ResolvedType {
|
||||
if (!(<ResolvedType>type).members) {
|
||||
if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
resolveClassOrInterfaceMembers(<InterfaceType>type);
|
||||
|
@ -3158,6 +3180,9 @@ namespace ts {
|
|||
else if (type.flags & TypeFlags.Union) {
|
||||
resolveUnionTypeMembers(<UnionType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Intersection) {
|
||||
resolveIntersectionTypeMembers(<IntersectionType>type);
|
||||
}
|
||||
else {
|
||||
resolveTypeReferenceMembers(<TypeReference>type);
|
||||
}
|
||||
|
@ -3168,16 +3193,16 @@ namespace ts {
|
|||
// Return properties of an object type or an empty array for other types
|
||||
function getPropertiesOfObjectType(type: Type): Symbol[] {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
return resolveObjectOrUnionTypeMembers(<ObjectType>type).properties;
|
||||
return resolveStructuredTypeMembers(<ObjectType>type).properties;
|
||||
}
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
// If the given type is an object type and that type has a property by the given name, return
|
||||
// the symbol for that property. Otherwise return undefined.
|
||||
// If the given type is an object type and that type has a property by the given name,
|
||||
// return the symbol for that property.Otherwise return undefined.
|
||||
function getPropertyOfObjectType(type: Type, name: string): Symbol {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
if (hasProperty(resolved.members, name)) {
|
||||
let symbol = resolved.members[name];
|
||||
if (symbolIsValue(symbol)) {
|
||||
|
@ -3187,20 +3212,23 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function getPropertiesOfUnionType(type: UnionType): Symbol[] {
|
||||
let result: Symbol[] = [];
|
||||
forEach(getPropertiesOfType(type.types[0]), prop => {
|
||||
let unionProp = getPropertyOfUnionType(type, prop.name);
|
||||
if (unionProp) {
|
||||
result.push(unionProp);
|
||||
function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
|
||||
for (let current of type.types) {
|
||||
for (let prop of getPropertiesOfType(current)) {
|
||||
getPropertyOfUnionOrIntersectionType(type, prop.name);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
// The properties of a union type are those that are present in all constituent types, so
|
||||
// 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[] {
|
||||
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;
|
||||
}
|
||||
|
||||
function createUnionProperty(unionType: UnionType, name: string): Symbol {
|
||||
let types = unionType.types;
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
|
||||
let types = containingType.types;
|
||||
let props: Symbol[];
|
||||
for (let current of types) {
|
||||
let type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
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;
|
||||
}
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
else {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!props) {
|
||||
return undefined;
|
||||
}
|
||||
if (props.length === 1) {
|
||||
return props[0];
|
||||
}
|
||||
let propTypes: Type[] = [];
|
||||
let declarations: Declaration[] = [];
|
||||
for (let prop of props) {
|
||||
|
@ -3261,19 +3298,19 @@ namespace ts {
|
|||
}
|
||||
propTypes.push(getTypeOfSymbol(prop));
|
||||
}
|
||||
let result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.UnionProperty, name);
|
||||
result.unionType = unionType;
|
||||
let result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name);
|
||||
result.containingType = containingType;
|
||||
result.declarations = declarations;
|
||||
result.type = getUnionType(propTypes);
|
||||
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getPropertyOfUnionType(type: UnionType, name: string): Symbol {
|
||||
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol {
|
||||
let properties = type.resolvedProperties || (type.resolvedProperties = {});
|
||||
if (hasProperty(properties, name)) {
|
||||
return properties[name];
|
||||
}
|
||||
let property = createUnionProperty(type, name);
|
||||
let property = createUnionOrIntersectionProperty(type, name);
|
||||
if (property) {
|
||||
properties[name] = property;
|
||||
}
|
||||
|
@ -3286,7 +3323,7 @@ namespace ts {
|
|||
function getPropertyOfType(type: Type, name: string): Symbol {
|
||||
type = getApparentType(type);
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(type);
|
||||
let resolved = resolveStructuredTypeMembers(type);
|
||||
if (hasProperty(resolved.members, name)) {
|
||||
let symbol = resolved.members[name];
|
||||
if (symbolIsValue(symbol)) {
|
||||
|
@ -3301,15 +3338,15 @@ namespace ts {
|
|||
}
|
||||
return getPropertyOfObjectType(globalObjectType, name);
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getPropertyOfUnionType(<UnionType>type, name);
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSignaturesOfObjectOrUnionType(type: Type, kind: SignatureKind): Signature[] {
|
||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): Signature[] {
|
||||
if (type.flags & TypeFlags.StructuredType) {
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures;
|
||||
}
|
||||
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
|
||||
// maps primitive types and type parameters are to their apparent types.
|
||||
function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] {
|
||||
return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
|
||||
return getSignaturesOfStructuredType(getApparentType(type), kind);
|
||||
}
|
||||
|
||||
function typeHasCallOrConstructSignatures(type: Type): boolean {
|
||||
let apparentType = getApparentType(type);
|
||||
if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
return resolved.callSignatures.length > 0
|
||||
|| resolved.constructSignatures.length > 0;
|
||||
if (apparentType.flags & TypeFlags.StructuredType) {
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
return resolved.callSignatures.length > 0 || resolved.constructSignatures.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): Type {
|
||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
function getIndexTypeOfStructuredType(type: Type, kind: IndexKind): Type {
|
||||
if (type.flags & TypeFlags.StructuredType) {
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
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
|
||||
// maps primitive types and type parameters are to their apparent types.
|
||||
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
|
||||
|
@ -3891,25 +3927,20 @@ namespace ts {
|
|||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function addTypeToSortedSet(sortedSet: Type[], type: Type) {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
addTypesToSortedSet(sortedSet, (<UnionType>type).types);
|
||||
function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) {
|
||||
if (type.flags & typeSetKind) {
|
||||
addTypesToSet(typeSet, (<UnionOrIntersectionType>type).types, typeSetKind);
|
||||
}
|
||||
else {
|
||||
let i = 0;
|
||||
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);
|
||||
}
|
||||
else if (!contains(typeSet, type)) {
|
||||
typeSet.push(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) {
|
||||
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
|
||||
// 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
|
||||
|
@ -3959,26 +3994,27 @@ namespace ts {
|
|||
if (types.length === 0) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
let sortedTypes: Type[] = [];
|
||||
addTypesToSortedSet(sortedTypes, types);
|
||||
let typeSet: Type[] = [];
|
||||
addTypesToSet(typeSet, types, TypeFlags.Union);
|
||||
typeSet.sort(compareTypeIds);
|
||||
if (noSubtypeReduction) {
|
||||
if (containsTypeAny(sortedTypes)) {
|
||||
if (containsTypeAny(typeSet)) {
|
||||
return anyType;
|
||||
}
|
||||
removeAllButLast(sortedTypes, undefinedType);
|
||||
removeAllButLast(sortedTypes, nullType);
|
||||
removeAllButLast(typeSet, undefinedType);
|
||||
removeAllButLast(typeSet, nullType);
|
||||
}
|
||||
else {
|
||||
removeSubtypes(sortedTypes);
|
||||
removeSubtypes(typeSet);
|
||||
}
|
||||
if (sortedTypes.length === 1) {
|
||||
return sortedTypes[0];
|
||||
if (typeSet.length === 1) {
|
||||
return typeSet[0];
|
||||
}
|
||||
let id = getTypeListId(sortedTypes);
|
||||
let id = getTypeListId(typeSet);
|
||||
let type = unionTypes[id];
|
||||
if (!type) {
|
||||
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(sortedTypes));
|
||||
type.types = sortedTypes;
|
||||
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(typeSet));
|
||||
type.types = typeSet;
|
||||
type.reducedType = noSubtypeReduction ? undefined : type;
|
||||
}
|
||||
return type;
|
||||
|
@ -4010,6 +4046,40 @@ namespace ts {
|
|||
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 {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
|
@ -4067,6 +4137,8 @@ namespace ts {
|
|||
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
|
||||
case SyntaxKind.UnionType:
|
||||
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
|
||||
case SyntaxKind.IntersectionType:
|
||||
return getTypeFromIntersectionTypeNode(<IntersectionTypeNode>node);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
|
||||
case SyntaxKind.FunctionType:
|
||||
|
@ -4254,6 +4326,9 @@ namespace ts {
|
|||
if (type.flags & TypeFlags.Union) {
|
||||
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;
|
||||
}
|
||||
|
@ -4294,7 +4369,7 @@ namespace ts {
|
|||
|
||||
function getTypeWithoutSignatures(type: Type): Type {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
if (resolved.constructSignatures.length) {
|
||||
let result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
|
||||
result.members = resolved.members;
|
||||
|
@ -4414,37 +4489,10 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
let saveErrorInfo = errorInfo;
|
||||
if (source.flags & TypeFlags.Union || target.flags & TypeFlags.Union) {
|
||||
if (relation === identityRelation) {
|
||||
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union) {
|
||||
if (result = unionTypeRelatedToUnionType(<UnionType>source, <UnionType>target)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if relationship holds for all type arguments
|
||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
|
||||
|
@ -4452,10 +4500,43 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
|
||||
// We have type references to same target type, see if relationship holds for all type arguments
|
||||
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
|
||||
return result;
|
||||
else if (relation !== identityRelation) {
|
||||
// Note that the "each" checks must precede the "some" checks to produce the correct results
|
||||
if (source.flags & TypeFlags.Union) {
|
||||
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.
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
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);
|
||||
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)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
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
|
||||
// the union comparison above if it is applicable.
|
||||
// the union or intersection comparison above if it is applicable.
|
||||
errorInfo = saveErrorInfo;
|
||||
if (result = isRelatedTo(sourceOrApparentType, target, reportErrors)) {
|
||||
return result;
|
||||
|
@ -4493,11 +4577,11 @@ namespace ts {
|
|||
return Ternary.False;
|
||||
}
|
||||
|
||||
function unionTypeRelatedToUnionType(source: UnionType, target: UnionType): Ternary {
|
||||
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
|
||||
let result = Ternary.True;
|
||||
let sourceTypes = source.types;
|
||||
for (let sourceType of sourceTypes) {
|
||||
let related = typeRelatedToUnionType(sourceType, target, false);
|
||||
let related = typeRelatedToSomeType(sourceType, target, false);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
@ -4506,7 +4590,7 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
function typeRelatedToUnionType(source: Type, target: UnionType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
let targetTypes = target.types;
|
||||
for (let i = 0, len = targetTypes.length; i < len; i++) {
|
||||
let related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
|
||||
|
@ -4517,7 +4601,31 @@ namespace ts {
|
|||
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 sourceTypes = source.types;
|
||||
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
|
||||
// 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.
|
||||
function objectTypeRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
||||
function objectTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (overflow) {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
@ -4647,7 +4755,7 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
function propertiesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
||||
function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return propertiesIdenticalTo(source, target);
|
||||
}
|
||||
|
@ -4731,7 +4839,10 @@ namespace ts {
|
|||
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 targetProperties = getPropertiesOfObjectType(target);
|
||||
if (sourceProperties.length !== targetProperties.length) {
|
||||
|
@ -4752,7 +4863,7 @@ namespace ts {
|
|||
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) {
|
||||
return signaturesIdenticalTo(source, target, kind);
|
||||
}
|
||||
|
@ -4878,7 +4989,7 @@ namespace ts {
|
|||
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 targetSignatures = getSignaturesOfType(target, kind);
|
||||
if (sourceSignatures.length !== targetSignatures.length) {
|
||||
|
@ -4895,7 +5006,7 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
function stringIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
||||
function stringIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return indexTypesIdenticalTo(IndexKind.String, source, target);
|
||||
}
|
||||
|
@ -4920,7 +5031,7 @@ namespace ts {
|
|||
return Ternary.True;
|
||||
}
|
||||
|
||||
function numberIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): Ternary {
|
||||
function numberIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return indexTypesIdenticalTo(IndexKind.Number, source, target);
|
||||
}
|
||||
|
@ -4953,7 +5064,7 @@ namespace ts {
|
|||
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 sourceType = getIndexTypeOfType(source, indexKind);
|
||||
if (!sourceType && !targetType) {
|
||||
|
@ -5337,11 +5448,11 @@ namespace ts {
|
|||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.Union) {
|
||||
let targetTypes = (<UnionType>target).types;
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
let targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
let typeParameterCount = 0;
|
||||
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) {
|
||||
if (t.flags & TypeFlags.TypeParameter && contains(context.typeParameters, t)) {
|
||||
typeParameter = <TypeParameter>t;
|
||||
|
@ -5351,16 +5462,19 @@ namespace ts {
|
|||
inferFromTypes(source, t);
|
||||
}
|
||||
}
|
||||
// If union contains a single naked type parameter, make a secondary inference to that type parameter
|
||||
if (typeParameterCount === 1) {
|
||||
// Next, if target is a union type containing a single naked type parameter, make a
|
||||
// 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++;
|
||||
inferFromTypes(source, typeParameter);
|
||||
inferiority--;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.Union) {
|
||||
// Source is a union type, infer from each consituent type
|
||||
let sourceTypes = (<UnionType>source).types;
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
// Source is a union or intersection type, infer from each consituent type
|
||||
let sourceTypes = (<UnionOrIntersectionType>source).types;
|
||||
for (let sourceType of sourceTypes) {
|
||||
inferFromTypes(sourceType, target);
|
||||
}
|
||||
|
@ -6343,13 +6457,13 @@ namespace ts {
|
|||
|
||||
function getTypeOfPropertyOfContextualType(type: Type, name: string) {
|
||||
return applyToContextualType(type, t => {
|
||||
let prop = getPropertyOfObjectType(t, name);
|
||||
let prop = t.flags & TypeFlags.StructuredType ? getPropertyOfType(t, name) : undefined;
|
||||
return prop ? getTypeOfSymbol(prop) : undefined;
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -6359,7 +6473,7 @@ namespace ts {
|
|||
|
||||
// Return true if the given contextual type provides an index signature of the given kind
|
||||
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
|
||||
|
@ -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
|
||||
// that signature is non-generic, return the signature. Otherwise return undefined.
|
||||
function getNonGenericSignature(type: Type): Signature {
|
||||
let signatures = getSignaturesOfObjectOrUnionType(type, SignatureKind.Call);
|
||||
let signatures = getSignaturesOfStructuredType(type, SignatureKind.Call);
|
||||
if (signatures.length === 1) {
|
||||
let signature = signatures[0];
|
||||
if (!signature.typeParameters) {
|
||||
|
@ -6538,7 +6652,7 @@ namespace ts {
|
|||
// The signature set of all constituent type with call signatures should match
|
||||
// So number of signatures allowed is either 0 or 1
|
||||
if (signatureList &&
|
||||
getSignaturesOfObjectOrUnionType(current, SignatureKind.Call).length > 1) {
|
||||
getSignaturesOfStructuredType(current, SignatureKind.Call).length > 1) {
|
||||
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.
|
||||
function getSingleCallSignature(type: Type): Signature {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 &&
|
||||
resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) {
|
||||
return resolved.callSignatures[0];
|
||||
|
@ -9131,8 +9245,8 @@ namespace ts {
|
|||
if (type.flags & kind) {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
let types = (<UnionType>type).types;
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
let types = (<UnionOrIntersectionType>type).types;
|
||||
for (let current of types) {
|
||||
if (current.flags & kind) {
|
||||
return true;
|
||||
|
@ -9143,13 +9257,13 @@ namespace ts {
|
|||
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 {
|
||||
if (type.flags & kind) {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
let types = (<UnionType>type).types;
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
let types = (<UnionOrIntersectionType>type).types;
|
||||
for (let current of types) {
|
||||
if (!(current.flags & kind)) {
|
||||
return false;
|
||||
|
@ -10174,7 +10288,7 @@ namespace ts {
|
|||
forEach(node.elementTypes, checkSourceElement);
|
||||
}
|
||||
|
||||
function checkUnionType(node: UnionTypeNode) {
|
||||
function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) {
|
||||
forEach(node.types, checkSourceElement);
|
||||
}
|
||||
|
||||
|
@ -12951,7 +13065,8 @@ namespace ts {
|
|||
case SyntaxKind.TupleType:
|
||||
return checkTupleType(<TupleTypeNode>node);
|
||||
case SyntaxKind.UnionType:
|
||||
return checkUnionType(<UnionTypeNode>node);
|
||||
case SyntaxKind.IntersectionType:
|
||||
return checkUnionOrIntersectionType(<UnionOrIntersectionTypeNode>node);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return checkSourceElement((<ParenthesizedTypeNode>node).type);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
|
@ -13593,10 +13708,10 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getRootSymbols(symbol: Symbol): Symbol[] {
|
||||
if (symbol.flags & SymbolFlags.UnionProperty) {
|
||||
if (symbol.flags & SymbolFlags.SyntheticProperty) {
|
||||
let symbols: Symbol[] = [];
|
||||
let name = symbol.name;
|
||||
forEach(getSymbolLinks(symbol).unionType.types, t => {
|
||||
forEach(getSymbolLinks(symbol).containingType.types, t => {
|
||||
symbols.push(getPropertyOfType(t, name));
|
||||
});
|
||||
return symbols;
|
||||
|
@ -13893,6 +14008,7 @@ namespace ts {
|
|||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.AnyKeyword:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -340,6 +340,8 @@ namespace ts {
|
|||
return emitTupleType(<TupleTypeNode>type);
|
||||
case SyntaxKind.UnionType:
|
||||
return emitUnionType(<UnionTypeNode>type);
|
||||
case SyntaxKind.IntersectionType:
|
||||
return emitIntersectionType(<IntersectionTypeNode>type);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return emitParenType(<ParenthesizedTypeNode>type);
|
||||
case SyntaxKind.FunctionType:
|
||||
|
@ -416,6 +418,10 @@ namespace ts {
|
|||
emitSeparatedList(type.types, " | ", emitType);
|
||||
}
|
||||
|
||||
function emitIntersectionType(type: IntersectionTypeNode) {
|
||||
emitSeparatedList(type.types, " & ", emitType);
|
||||
}
|
||||
|
||||
function emitParenType(type: ParenthesizedTypeNode) {
|
||||
write("(");
|
||||
emitType(type.type);
|
||||
|
|
|
@ -115,7 +115,8 @@ namespace ts {
|
|||
case SyntaxKind.TupleType:
|
||||
return visitNodes(cbNodes, (<TupleTypeNode>node).elementTypes);
|
||||
case SyntaxKind.UnionType:
|
||||
return visitNodes(cbNodes, (<UnionTypeNode>node).types);
|
||||
case SyntaxKind.IntersectionType:
|
||||
return visitNodes(cbNodes, (<UnionOrIntersectionTypeNode>node).types);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return visitNode(cbNode, (<ParenthesizedTypeNode>node).type);
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
|
@ -2401,22 +2402,30 @@ namespace ts {
|
|||
return type;
|
||||
}
|
||||
|
||||
function parseUnionTypeOrHigher(): TypeNode {
|
||||
let type = parseArrayTypeOrHigher();
|
||||
if (token === SyntaxKind.BarToken) {
|
||||
function parseUnionOrIntersectionType(kind: SyntaxKind, parseConstituentType: () => TypeNode, operator: SyntaxKind): TypeNode {
|
||||
let type = parseConstituentType();
|
||||
if (token === operator) {
|
||||
let types = <NodeArray<TypeNode>>[type];
|
||||
types.pos = type.pos;
|
||||
while (parseOptional(SyntaxKind.BarToken)) {
|
||||
types.push(parseArrayTypeOrHigher());
|
||||
while (parseOptional(operator)) {
|
||||
types.push(parseConstituentType());
|
||||
}
|
||||
types.end = getNodeEnd();
|
||||
let node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
|
||||
let node = <UnionOrIntersectionTypeNode>createNode(kind, type.pos);
|
||||
node.types = types;
|
||||
type = finishNode(node);
|
||||
}
|
||||
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 {
|
||||
if (token === SyntaxKind.LessThanToken) {
|
||||
return true;
|
||||
|
|
|
@ -191,6 +191,7 @@ namespace ts {
|
|||
ArrayType,
|
||||
TupleType,
|
||||
UnionType,
|
||||
IntersectionType,
|
||||
ParenthesizedType,
|
||||
// Binding patterns
|
||||
ObjectBindingPattern,
|
||||
|
@ -667,10 +668,14 @@ namespace ts {
|
|||
elementTypes: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface UnionTypeNode extends TypeNode {
|
||||
export interface UnionOrIntersectionTypeNode extends TypeNode {
|
||||
types: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface UnionTypeNode extends UnionOrIntersectionTypeNode { }
|
||||
|
||||
export interface IntersectionTypeNode extends UnionOrIntersectionTypeNode { }
|
||||
|
||||
export interface ParenthesizedTypeNode extends TypeNode {
|
||||
type: TypeNode;
|
||||
}
|
||||
|
@ -1573,7 +1578,7 @@ namespace ts {
|
|||
Merged = 0x02000000, // Merged symbol (created during program binding)
|
||||
Transient = 0x04000000, // Transient symbol (created during type check)
|
||||
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
|
||||
ExportStar = 0x40000000, // Export * declaration
|
||||
|
||||
|
@ -1652,7 +1657,7 @@ namespace ts {
|
|||
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
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
|
||||
exportsChecked?: boolean; // True if exports of external module have been checked
|
||||
isNestedRedeclaration?: boolean; // True if symbol is block scoped redeclaration
|
||||
|
@ -1721,17 +1726,18 @@ namespace ts {
|
|||
Interface = 0x00000800, // Interface
|
||||
Reference = 0x00001000, // Generic type reference
|
||||
Tuple = 0x00002000, // Tuple
|
||||
Union = 0x00004000, // Union
|
||||
Anonymous = 0x00008000, // Anonymous
|
||||
Instantiated = 0x00010000, // Instantiated anonymous type
|
||||
Union = 0x00004000, // Union (T | U)
|
||||
Intersection = 0x00008000, // Intersection (T & U)
|
||||
Anonymous = 0x00010000, // Anonymous
|
||||
Instantiated = 0x00020000, // Instantiated anonymous type
|
||||
/* @internal */
|
||||
FromSignature = 0x00020000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00040000, // Originates in an object literal
|
||||
FromSignature = 0x00040000, // Created for signature assignment check
|
||||
ObjectLiteral = 0x00080000, // Originates in an object literal
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00080000, // Type is or contains Undefined or Null type
|
||||
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00100000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00200000, // Type of symbol primitive introduced in ES6
|
||||
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
|
||||
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
|
@ -1740,6 +1746,8 @@ namespace ts {
|
|||
StringLike = String | StringLiteral,
|
||||
NumberLike = Number | Enum,
|
||||
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
|
||||
UnionOrIntersection = Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral
|
||||
}
|
||||
|
@ -1799,7 +1807,7 @@ namespace ts {
|
|||
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
|
||||
/* @internal */
|
||||
reducedType: Type; // Reduced union type (all subtypes removed)
|
||||
|
@ -1807,9 +1815,13 @@ namespace ts {
|
|||
resolvedProperties: SymbolTable; // Cache of resolved properties
|
||||
}
|
||||
|
||||
export interface UnionType extends UnionOrIntersectionType { }
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType { }
|
||||
|
||||
/* @internal */
|
||||
// Resolved object or union type
|
||||
export interface ResolvedType extends ObjectType, UnionType {
|
||||
// Resolved object, union, or intersection type
|
||||
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
|
||||
members: SymbolTable; // Properties by name
|
||||
properties: Symbol[]; // Properties
|
||||
callSignatures: Signature[]; // Call signatures of type
|
||||
|
|
|
@ -3689,7 +3689,7 @@ namespace ts {
|
|||
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
||||
|
||||
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
|
||||
let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
|
||||
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 symbol correspond to the union property - bail out
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.UnionProperty)) {
|
||||
if (symbol.parent || (symbol.flags & SymbolFlags.SyntheticProperty)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,26 +75,26 @@ function delint(sourceFile) {
|
|||
delintNode(sourceFile);
|
||||
function delintNode(node) {
|
||||
switch (node.kind) {
|
||||
case 195 /* ForStatement */:
|
||||
case 196 /* ForInStatement */:
|
||||
case 194 /* WhileStatement */:
|
||||
case 193 /* DoStatement */:
|
||||
if (node.statement.kind !== 188 /* Block */) {
|
||||
case 196 /* ForStatement */:
|
||||
case 197 /* ForInStatement */:
|
||||
case 195 /* WhileStatement */:
|
||||
case 194 /* DoStatement */:
|
||||
if (node.statement.kind !== 189 /* Block */) {
|
||||
report(node, "A looping statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
case 192 /* IfStatement */:
|
||||
case 193 /* IfStatement */:
|
||||
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.");
|
||||
}
|
||||
if (ifStatement.elseStatement &&
|
||||
ifStatement.elseStatement.kind !== 188 /* Block */ &&
|
||||
ifStatement.elseStatement.kind !== 192 /* IfStatement */) {
|
||||
ifStatement.elseStatement.kind !== 189 /* Block */ &&
|
||||
ifStatement.elseStatement.kind !== 193 /* IfStatement */) {
|
||||
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
|
||||
}
|
||||
break;
|
||||
case 177 /* BinaryExpression */:
|
||||
case 178 /* BinaryExpression */:
|
||||
var op = node.operatorToken.kind;
|
||||
if (op === 29 /* EqualsEqualsToken */ || op == 30 /* ExclamationEqualsToken */) {
|
||||
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))
|
||||
|
||||
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))
|
||||
>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 : Symbol(run, Decl(typeParameterExtendingUnion1.ts, 2, 33))
|
||||
|
|
|
@ -20,9 +20,9 @@ function run(a: Cat | Dog) {
|
|||
>Dog : Symbol(Dog, Decl(typeParameterExtendingUnion2.ts, 1, 33))
|
||||
|
||||
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))
|
||||
>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) {
|
||||
|
@ -34,9 +34,9 @@ function f<T extends Cat | Dog>(a: T) {
|
|||
>T : Symbol(T, Decl(typeParameterExtendingUnion2.ts, 8, 11))
|
||||
|
||||
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))
|
||||
>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 : 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