Merge pull request #13366 from Microsoft/fixMappedTypeCombinedMappers

Fix bug in recursive mapped type instantiation
This commit is contained in:
Anders Hejlsberg 2017-01-09 09:56:52 -10:00 committed by GitHub
commit f667b5cf50
4 changed files with 74 additions and 4 deletions

View File

@ -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 = <TypeParameter>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;
});

View File

@ -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<T, A> = {
readonly[P in keyof T]: {
value: T[P];
also: A;
readonly children: Meta<T[P], A>;
};
}
interface Input {
x: string;
y: number;
}
declare const output: Meta<Input, boolean>;
const shouldFail: { important: boolean } = output.x.children;
~~~~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type '{ important: boolean; }'.

View File

@ -0,0 +1,24 @@
//// [mappedTypeWithCombinedTypeMappers.ts]
// Repro from #13351
type Meta<T, A> = {
readonly[P in keyof T]: {
value: T[P];
also: A;
readonly children: Meta<T[P], A>;
};
}
interface Input {
x: string;
y: number;
}
declare const output: Meta<Input, boolean>;
const shouldFail: { important: boolean } = output.x.children;
//// [mappedTypeWithCombinedTypeMappers.js]
// Repro from #13351
var shouldFail = output.x.children;

View File

@ -0,0 +1,18 @@
// Repro from #13351
type Meta<T, A> = {
readonly[P in keyof T]: {
value: T[P];
also: A;
readonly children: Meta<T[P], A>;
};
}
interface Input {
x: string;
y: number;
}
declare const output: Meta<Input, boolean>;
const shouldFail: { important: boolean } = output.x.children;