diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b063de5cc1a03..2c22f3a33d073 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14794,7 +14794,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type)); } - function getResolvedApparentTypeOfMappedType(type: MappedType) { + function getResolvedApparentTypeOfMappedType(type: MappedType): Type { const target = (type.target ?? type) as MappedType; const typeVariable = getHomomorphicTypeVariable(target); if (typeVariable && !target.declaration.nameType) { @@ -14802,7 +14802,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (constraint.flags & TypeFlags.Index) { const baseConstraint = getBaseConstraintOfType((constraint as IndexType).type); if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { - return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); + const modifiersType = getModifiersTypeFromMappedType(type); + return instantiateType(target, prependTypeMapping(typeVariable, isGenericMappedType(modifiersType) ? getResolvedApparentTypeOfMappedType(modifiersType) : baseConstraint, type.mapper)); } } } diff --git a/tests/baselines/reference/homomorphicMappedTypeNested1.symbols b/tests/baselines/reference/homomorphicMappedTypeNested1.symbols new file mode 100644 index 0000000000000..a94ccc4c34dbd --- /dev/null +++ b/tests/baselines/reference/homomorphicMappedTypeNested1.symbols @@ -0,0 +1,61 @@ +//// [tests/cases/compiler/homomorphicMappedTypeNested1.ts] //// + +=== homomorphicMappedTypeNested1.ts === +// https://github.com/microsoft/TypeScript/issues/58060 + +type ValueType = string; +>ValueType : Symbol(ValueType, Decl(homomorphicMappedTypeNested1.ts, 0, 0)) + +type Box = { v: T }; +>Box : Symbol(Box, Decl(homomorphicMappedTypeNested1.ts, 2, 24)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 4, 9)) +>ValueType : Symbol(ValueType, Decl(homomorphicMappedTypeNested1.ts, 0, 0)) +>v : Symbol(v, Decl(homomorphicMappedTypeNested1.ts, 4, 33)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 4, 9)) + +type Test = T; +>Test : Symbol(Test, Decl(homomorphicMappedTypeNested1.ts, 4, 41)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 6, 10)) +>ValueType : Symbol(ValueType, Decl(homomorphicMappedTypeNested1.ts, 0, 0)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 6, 10)) + +type UnboxArray = { +>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNested1.ts, 6, 37)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 8, 16)) + + [K in keyof T]: T[K] extends Box ? R : never; +>K : Symbol(K, Decl(homomorphicMappedTypeNested1.ts, 9, 3)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 8, 16)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 8, 16)) +>K : Symbol(K, Decl(homomorphicMappedTypeNested1.ts, 9, 3)) +>Box : Symbol(Box, Decl(homomorphicMappedTypeNested1.ts, 2, 24)) +>R : Symbol(R, Decl(homomorphicMappedTypeNested1.ts, 9, 40)) +>R : Symbol(R, Decl(homomorphicMappedTypeNested1.ts, 9, 40)) + +}; + +type Identity = { [K in keyof T]: T[K] }; +>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNested1.ts, 10, 2)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 12, 14)) +>K : Symbol(K, Decl(homomorphicMappedTypeNested1.ts, 12, 22)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 12, 14)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 12, 14)) +>K : Symbol(K, Decl(homomorphicMappedTypeNested1.ts, 12, 22)) + +declare function fn>>( +>fn : Symbol(fn, Decl(homomorphicMappedTypeNested1.ts, 12, 44)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 14, 20)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>Box : Symbol(Box, Decl(homomorphicMappedTypeNested1.ts, 2, 24)) +>ValueType : Symbol(ValueType, Decl(homomorphicMappedTypeNested1.ts, 0, 0)) + + ...args: T +>args : Symbol(args, Decl(homomorphicMappedTypeNested1.ts, 14, 53)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 14, 20)) + +): Test>>; +>Test : Symbol(Test, Decl(homomorphicMappedTypeNested1.ts, 4, 41)) +>Identity : Symbol(Identity, Decl(homomorphicMappedTypeNested1.ts, 10, 2)) +>UnboxArray : Symbol(UnboxArray, Decl(homomorphicMappedTypeNested1.ts, 6, 37)) +>T : Symbol(T, Decl(homomorphicMappedTypeNested1.ts, 14, 20)) + diff --git a/tests/baselines/reference/homomorphicMappedTypeNested1.types b/tests/baselines/reference/homomorphicMappedTypeNested1.types new file mode 100644 index 0000000000000..16f670ee37607 --- /dev/null +++ b/tests/baselines/reference/homomorphicMappedTypeNested1.types @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/homomorphicMappedTypeNested1.ts] //// + +=== homomorphicMappedTypeNested1.ts === +// https://github.com/microsoft/TypeScript/issues/58060 + +type ValueType = string; +>ValueType : string +> : ^^^^^^ + +type Box = { v: T }; +>Box : Box +> : ^^^^^^ +>v : T +> : ^ + +type Test = T; +>Test : T +> : ^ + +type UnboxArray = { +>UnboxArray : UnboxArray +> : ^^^^^^^^^^^^^ + + [K in keyof T]: T[K] extends Box ? R : never; +}; + +type Identity = { [K in keyof T]: T[K] }; +>Identity : Identity +> : ^^^^^^^^^^^ + +declare function fn>>( +>fn : []>(...args: T) => Test>> +> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ + + ...args: T +>args : T +> : ^ + +): Test>>; + diff --git a/tests/cases/compiler/homomorphicMappedTypeNested1.ts b/tests/cases/compiler/homomorphicMappedTypeNested1.ts new file mode 100644 index 0000000000000..89b63a1ca1b27 --- /dev/null +++ b/tests/cases/compiler/homomorphicMappedTypeNested1.ts @@ -0,0 +1,20 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/58060 + +type ValueType = string; + +type Box = { v: T }; + +type Test = T; + +type UnboxArray = { + [K in keyof T]: T[K] extends Box ? R : never; +}; + +type Identity = { [K in keyof T]: T[K] }; + +declare function fn>>( + ...args: T +): Test>>;