From b70784ef8f3ba3fd21750b9acf275dd7edcc7fe7 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 19 Mar 2023 08:13:57 -0700 Subject: [PATCH] Improve detection of type variables in instantiated object types (#53246) --- src/compiler/checker.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a12a38c4c2f..cc64670dd99 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18705,6 +18705,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result = target.objectFlags & ObjectFlags.Reference ? createDeferredTypeReference((type as DeferredTypeReference).target, (type as DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) : target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) : instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments); + // If none of the type arguments for the outer type parameters contain type variables, it follows + // that the instantiated type doesn't reference type variables. + if (result.flags & TypeFlags.ObjectFlagsType && !((result as ObjectFlagsType).objectFlags & ObjectFlags.CouldContainTypeVariablesComputed)) { + (result as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | + (some(typeArguments, couldContainTypeVariables) ? ObjectFlags.CouldContainTypeVariables : 0); + } target.instantiations.set(id, result); } return result; @@ -18875,7 +18881,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): AnonymousType { - const result = createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol) as AnonymousType; + const result = createObjectType(type.objectFlags & ~(ObjectFlags.CouldContainTypeVariablesComputed | ObjectFlags.CouldContainTypeVariables) | ObjectFlags.Instantiated, type.symbol) as AnonymousType; if (type.objectFlags & ObjectFlags.Mapped) { (result as MappedType).declaration = (type as MappedType).declaration; // C.f. instantiateSignature @@ -23887,7 +23893,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const result = !!(type.flags & TypeFlags.Instantiable || type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && ( - objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || forEach(getTypeArguments(type as TypeReference), couldContainTypeVariables)) || + objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || some(getTypeArguments(type as TypeReference), couldContainTypeVariables)) || objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations || objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)) || type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType).types, couldContainTypeVariables));