diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1bb5c6a297765..63f6fda4225f1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17685,7 +17685,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // eagerly using the constraint type of 'this' at the given location. if (isGenericIndexType(indexType) || (accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType ? isGenericTupleType(objectType) && !indexTypeLessThan(indexType, objectType.target.fixedLength) : - isGenericObjectType(objectType) && !(isTupleType(objectType) && indexTypeLessThan(indexType, objectType.target.fixedLength)) || isGenericReducibleType(objectType))) { + isGenericObjectType(objectType) && !(isTupleType(objectType) && indexTypeLessThan(indexType, objectType.target.fixedLength)) || !(accessFlags & AccessFlags.ResolveReducibleTypes) && isGenericReducibleType(objectType))) { if (objectType.flags & TypeFlags.AnyOrUnknown) { return objectType; } @@ -24511,6 +24511,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } + // The following is a targeted fix to allow higher-kinded types to be emulated using the technique in #53970. + // Specifically, when an indexed access type was deferred because it has a reducible object type, here we force + // resolution of the type and then infer to the result. + if (target.flags & TypeFlags.IndexedAccess && isGenericReducibleType((target as IndexedAccessType).objectType)) { + const instantiated = getIndexedAccessType((target as IndexedAccessType).objectType, (target as IndexedAccessType).indexType, AccessFlags.ResolveReducibleTypes); + if (instantiated && instantiated !== target) { + inferFromTypes(source, instantiated); + } + } } if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target)) && diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c97bbaffa2834..122ed908792fa 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6593,15 +6593,16 @@ export interface TypeParameter extends InstantiableType { export const enum AccessFlags { None = 0, IncludeUndefined = 1 << 0, - NoIndexSignatures = 1 << 1, - Writing = 1 << 2, - CacheSymbol = 1 << 3, - NoTupleBoundsCheck = 1 << 4, - ExpressionPosition = 1 << 5, - ReportDeprecated = 1 << 6, - SuppressNoImplicitAnyError = 1 << 7, - Contextual = 1 << 8, - Persistent = IncludeUndefined, + ResolveReducibleTypes = 1 << 1, + NoIndexSignatures = 1 << 2, + Writing = 1 << 3, + CacheSymbol = 1 << 4, + NoTupleBoundsCheck = 1 << 5, + ExpressionPosition = 1 << 6, + ReportDeprecated = 1 << 7, + SuppressNoImplicitAnyError = 1 << 8, + Contextual = 1 << 9, + Persistent = IncludeUndefined | ResolveReducibleTypes, } // Indexed access types (TypeFlags.IndexedAccess)