diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8cacad8eb7e8a..0456ecce73a90 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6558,6 +6558,12 @@ namespace ts { return mapper; } + function createReplacementMapper(source: Type, target: Type, baseMapper: TypeMapper) { + const mapper: TypeMapper = t => t === source ? target : baseMapper(t); + mapper.mappedTypes = baseMapper.mappedTypes; + return mapper; + } + function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter { const result = createType(TypeFlags.TypeParameter); result.symbol = typeParameter.symbol; @@ -6656,10 +6662,7 @@ namespace ts { if (typeVariable !== mappedTypeVariable) { return mapType(mappedTypeVariable, t => { if (isMappableType(t)) { - const replacementMapper = createTypeMapper([typeVariable], [t]); - const combinedMapper = mapper.mappedTypes && mapper.mappedTypes.length === 1 ? replacementMapper : combineTypeMappers(replacementMapper, mapper); - combinedMapper.mappedTypes = mapper.mappedTypes; - return instantiateMappedObjectType(type, combinedMapper); + return instantiateMappedObjectType(type, createReplacementMapper(typeVariable, t, mapper)); } return t; }); diff --git a/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.errors.txt b/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.errors.txt new file mode 100644 index 0000000000000..56837dd787e49 --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.errors.txt @@ -0,0 +1,25 @@ +tests/cases/compiler/mappedTypeWithCombinedTypeMappers.ts(18,7): error TS2322: Type 'string' is not assignable to type '{ important: boolean; }'. + + +==== tests/cases/compiler/mappedTypeWithCombinedTypeMappers.ts (1 errors) ==== + // Repro from #13351 + + type Meta = { + readonly[P in keyof T]: { + value: T[P]; + also: A; + readonly children: Meta; + }; + } + + interface Input { + x: string; + y: number; + } + + declare const output: Meta; + + const shouldFail: { important: boolean } = output.x.children; + ~~~~~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type '{ important: boolean; }'. + \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.js b/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.js new file mode 100644 index 0000000000000..a445f2eebc5ac --- /dev/null +++ b/tests/baselines/reference/mappedTypeWithCombinedTypeMappers.js @@ -0,0 +1,24 @@ +//// [mappedTypeWithCombinedTypeMappers.ts] +// Repro from #13351 + +type Meta = { + readonly[P in keyof T]: { + value: T[P]; + also: A; + readonly children: Meta; + }; +} + +interface Input { + x: string; + y: number; +} + +declare const output: Meta; + +const shouldFail: { important: boolean } = output.x.children; + + +//// [mappedTypeWithCombinedTypeMappers.js] +// Repro from #13351 +var shouldFail = output.x.children; diff --git a/tests/cases/compiler/mappedTypeWithCombinedTypeMappers.ts b/tests/cases/compiler/mappedTypeWithCombinedTypeMappers.ts new file mode 100644 index 0000000000000..9c6d8479b2e69 --- /dev/null +++ b/tests/cases/compiler/mappedTypeWithCombinedTypeMappers.ts @@ -0,0 +1,18 @@ +// Repro from #13351 + +type Meta = { + readonly[P in keyof T]: { + value: T[P]; + also: A; + readonly children: Meta; + }; +} + +interface Input { + x: string; + y: number; +} + +declare const output: Meta; + +const shouldFail: { important: boolean } = output.x.children;