diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 546d8412c98..1ed8cb8c6ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4001,8 +4001,7 @@ namespace ts { concatenate((type).typeArguments, [thisArgument || (type).target.thisType])); } if (type.flags & TypeFlags.Tuple) { - resolveTupleTypeMembers(type as TupleType, thisArgument); - return type; + return createTupleType((type as TupleType).elementTypes, thisArgument); } return type; } @@ -4104,11 +4103,11 @@ namespace ts { return members; } - function resolveTupleTypeMembers(type: TupleType, thisArgument?: Type) { + function resolveTupleTypeMembers(type: TupleType) { const arrayElementType = getUnionType(type.elementTypes); // Make the tuple type itself the 'this' type by including an extra type argument // (Unless it's provided in the case that the tuple is a type parameter constraint) - const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, thisArgument || type])); + const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, type.thisType || type])); const members = createTupleTypeMemberSymbols(type.elementTypes); addInheritedMembers(members, arrayType.properties); setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo); @@ -5235,15 +5234,20 @@ namespace ts { return links.resolvedType; } - function createTupleType(elementTypes: Type[]) { - const id = getTypeListId(elementTypes); - return tupleTypes[id] || (tupleTypes[id] = createNewTupleType(elementTypes)); + function createTupleType(elementTypes: Type[], thisType?: Type) { + let id = getTypeListId(elementTypes); + if (thisType) { + id += ',' + thisType.id; + } + + return tupleTypes[id] || (tupleTypes[id] = createNewTupleType(elementTypes, thisType)); } - function createNewTupleType(elementTypes: Type[]) { + function createNewTupleType(elementTypes: Type[], thisType?: Type) { const propagatedFlags = getPropagatingFlagsOfTypes(elementTypes, /*excludeKinds*/ 0); const type = createObjectType(TypeFlags.Tuple | propagatedFlags); type.elementTypes = elementTypes; + type.thisType = thisType; return type; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a6e860450c6..25630059bf0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2371,6 +2371,7 @@ namespace ts { export interface TupleType extends ObjectType { elementTypes: Type[]; // Element types + thisType?: Type; // This-type of tuple (only needed for tuples that are constraints of type parameters) } export interface UnionOrIntersectionType extends Type {