diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 450fcfe1da4..6de1b5aa624 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4326,10 +4326,13 @@ namespace ts { function getTypeWithThisArgument(type: Type, thisArgument?: Type): Type { if (getObjectFlags(type) & ObjectFlags.Reference) { - return createTypeReference((type).target, - concatenate((type).typeArguments, [thisArgument || (type).target.thisType])); + const target = (type).target; + const typeArguments = (type).typeArguments; + if (length(target.typeParameters) === length(typeArguments)) { + return createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType])); + } } - if (type.flags & TypeFlags.Intersection) { + else if (type.flags & TypeFlags.Intersection) { return getIntersectionType(map((type).types, t => getTypeWithThisArgument(t, thisArgument))); } return type; @@ -4858,6 +4861,10 @@ namespace ts { } } + function getApparentTypeOfIntersectionType(type: IntersectionType) { + return type.resolvedIndexType || (type.resolvedApparentType = getTypeWithThisArgument(type, type)); + } + /** * For a type parameter, return the base constraint of the type parameter. For the string, number, * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the @@ -4865,7 +4872,8 @@ namespace ts { */ function getApparentType(type: Type): Type { const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(type) || emptyObjectType : type; - return t.flags & TypeFlags.StringLike ? globalStringType : + return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(type) : + t.flags & TypeFlags.StringLike ? globalStringType : t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() : diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 654b1bc2912..47a6e2e70a8 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -202,6 +202,10 @@ namespace ts { GreaterThan = 1 } + export function length(array: any[]) { + return array ? array.length : 0; + } + /** * Iterates through 'array' by index and performs the callback on each element of array until the callback * returns a truthy value, then returns that value. diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 65cd4031613..6b5c670a9fa 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2961,7 +2961,10 @@ export interface UnionType extends UnionOrIntersectionType { } - export interface IntersectionType extends UnionOrIntersectionType { } + export interface IntersectionType extends UnionOrIntersectionType { + /* @internal */ + resolvedApparentType: Type; + } export type StructuredType = ObjectType | UnionType | IntersectionType;