diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76059a8ba28..33b3505661a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6652,17 +6652,19 @@ namespace ts { const constraintType = getConstraintTypeFromMappedType(type); if (constraintType.flags & TypeFlags.Index) { const typeVariable = (constraintType).type; - const mappedTypeVariable = instantiateType(typeVariable, mapper); - if (typeVariable !== mappedTypeVariable) { - return mapType(mappedTypeVariable, t => { - if (isMappableType(t)) { - const replacementMapper = createUnaryTypeMapper(typeVariable, t); - const combinedMapper = mapper.mappedTypes && mapper.mappedTypes.length === 1 ? replacementMapper : combineTypeMappers(replacementMapper, mapper); - combinedMapper.mappedTypes = mapper.mappedTypes; - return instantiateMappedObjectType(type, combinedMapper); - } - return t; - }); + if (typeVariable.flags & TypeFlags.TypeParameter) { + const mappedTypeVariable = instantiateType(typeVariable, mapper); + if (typeVariable !== mappedTypeVariable) { + return mapType(mappedTypeVariable, t => { + if (isMappableType(t)) { + const replacementMapper = createUnaryTypeMapper(typeVariable, t); + const combinedMapper = mapper.mappedTypes && mapper.mappedTypes.length === 1 ? replacementMapper : combineTypeMappers(replacementMapper, mapper); + combinedMapper.mappedTypes = mapper.mappedTypes; + return instantiateMappedObjectType(type, combinedMapper); + } + return t; + }); + } } } return instantiateMappedObjectType(type, mapper); diff --git a/tests/baselines/reference/mappedTypes4.js b/tests/baselines/reference/mappedTypes4.js index bb003b1a1ec..963538d2269 100644 --- a/tests/baselines/reference/mappedTypes4.js +++ b/tests/baselines/reference/mappedTypes4.js @@ -58,7 +58,19 @@ type DeepReadonlyFoo = { }; var x1: DeepReadonly; -var x1: DeepReadonlyFoo; +var x1: DeepReadonlyFoo; + +// Repro from #13232 + +type Z = { a: number }; +type Clone = { + [P in keyof (T & {})]: T[P]; +}; +type M = Clone; // M should be { a: number } + +var z1: Z; +var z1: Clone; + //// [mappedTypes4.js] function boxify(obj) { @@ -76,6 +88,8 @@ function f1(x) { } var x1; var x1; +var z1; +var z1; //// [mappedTypes4.d.ts] @@ -127,3 +141,12 @@ declare type DeepReadonlyFoo = { }; declare var x1: DeepReadonly; declare var x1: DeepReadonlyFoo; +declare type Z = { + a: number; +}; +declare type Clone = { + [P in keyof (T & {})]: T[P]; +}; +declare type M = Clone; +declare var z1: Z; +declare var z1: Clone; diff --git a/tests/baselines/reference/mappedTypes4.symbols b/tests/baselines/reference/mappedTypes4.symbols index b57adfe9954..ed108b47d78 100644 --- a/tests/baselines/reference/mappedTypes4.symbols +++ b/tests/baselines/reference/mappedTypes4.symbols @@ -196,3 +196,34 @@ var x1: DeepReadonlyFoo; >x1 : Symbol(x1, Decl(mappedTypes4.ts, 58, 3), Decl(mappedTypes4.ts, 59, 3)) >DeepReadonlyFoo : Symbol(DeepReadonlyFoo, Decl(mappedTypes4.ts, 50, 2)) +// Repro from #13232 + +type Z = { a: number }; +>Z : Symbol(Z, Decl(mappedTypes4.ts, 59, 24)) +>a : Symbol(a, Decl(mappedTypes4.ts, 63, 10)) + +type Clone = { +>Clone : Symbol(Clone, Decl(mappedTypes4.ts, 63, 23)) +>T : Symbol(T, Decl(mappedTypes4.ts, 64, 11)) + + [P in keyof (T & {})]: T[P]; +>P : Symbol(P, Decl(mappedTypes4.ts, 65, 3)) +>T : Symbol(T, Decl(mappedTypes4.ts, 64, 11)) +>T : Symbol(T, Decl(mappedTypes4.ts, 64, 11)) +>P : Symbol(P, Decl(mappedTypes4.ts, 65, 3)) + +}; +type M = Clone; // M should be { a: number } +>M : Symbol(M, Decl(mappedTypes4.ts, 66, 2)) +>Clone : Symbol(Clone, Decl(mappedTypes4.ts, 63, 23)) +>Z : Symbol(Z, Decl(mappedTypes4.ts, 59, 24)) + +var z1: Z; +>z1 : Symbol(z1, Decl(mappedTypes4.ts, 69, 3), Decl(mappedTypes4.ts, 70, 3)) +>Z : Symbol(Z, Decl(mappedTypes4.ts, 59, 24)) + +var z1: Clone; +>z1 : Symbol(z1, Decl(mappedTypes4.ts, 69, 3), Decl(mappedTypes4.ts, 70, 3)) +>Clone : Symbol(Clone, Decl(mappedTypes4.ts, 63, 23)) +>Z : Symbol(Z, Decl(mappedTypes4.ts, 59, 24)) + diff --git a/tests/baselines/reference/mappedTypes4.types b/tests/baselines/reference/mappedTypes4.types index cc492d82120..a2fec06ccec 100644 --- a/tests/baselines/reference/mappedTypes4.types +++ b/tests/baselines/reference/mappedTypes4.types @@ -211,3 +211,34 @@ var x1: DeepReadonlyFoo; >x1 : DeepReadonly >DeepReadonlyFoo : DeepReadonlyFoo +// Repro from #13232 + +type Z = { a: number }; +>Z : Z +>a : number + +type Clone = { +>Clone : Clone +>T : T + + [P in keyof (T & {})]: T[P]; +>P : P +>T : T +>T : T +>P : P + +}; +type M = Clone; // M should be { a: number } +>M : Clone +>Clone : Clone +>Z : Z + +var z1: Z; +>z1 : Z +>Z : Z + +var z1: Clone; +>z1 : Z +>Clone : Clone +>Z : Z + diff --git a/tests/cases/conformance/types/mapped/mappedTypes4.ts b/tests/cases/conformance/types/mapped/mappedTypes4.ts index 74b3e395f32..4def192d602 100644 --- a/tests/cases/conformance/types/mapped/mappedTypes4.ts +++ b/tests/cases/conformance/types/mapped/mappedTypes4.ts @@ -59,4 +59,15 @@ type DeepReadonlyFoo = { }; var x1: DeepReadonly; -var x1: DeepReadonlyFoo; \ No newline at end of file +var x1: DeepReadonlyFoo; + +// Repro from #13232 + +type Z = { a: number }; +type Clone = { + [P in keyof (T & {})]: T[P]; +}; +type M = Clone; // M should be { a: number } + +var z1: Z; +var z1: Clone;