diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bc93cce86b8..77d27de786b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6850,7 +6850,7 @@ namespace ts { function getConstraintTypeFromMappedType(type: MappedType) { return type.constraintType || - (type.constraintType = instantiateType(getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)), type.mapper || identityMapper) || errorType); + (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType); } function getTemplateTypeFromMappedType(type: MappedType) { @@ -10413,6 +10413,12 @@ namespace ts { const result = createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol); if (type.objectFlags & ObjectFlags.Mapped) { (result).declaration = (type).declaration; + // C.f. instantiateSignature + const origTypeParameter = getTypeParameterFromMappedType(type); + const freshTypeParameter = cloneTypeParameter(origTypeParameter); + (result).typeParameter = freshTypeParameter; + mapper = combineTypeMappers(makeUnaryTypeMapper(origTypeParameter, freshTypeParameter), mapper); + freshTypeParameter.mapper = mapper; } result.target = type; result.mapper = mapper; diff --git a/tests/baselines/reference/mappedTypeParameterConstraint.js b/tests/baselines/reference/mappedTypeParameterConstraint.js new file mode 100644 index 00000000000..f7715f17993 --- /dev/null +++ b/tests/baselines/reference/mappedTypeParameterConstraint.js @@ -0,0 +1,14 @@ +//// [mappedTypeParameterConstraint.ts] +// Repro for #27596 + +type MyMap = {[P in keyof T]: T[keyof T]}; +function foo(arg: U): MyMap { + return arg; +} + + +//// [mappedTypeParameterConstraint.js] +// Repro for #27596 +function foo(arg) { + return arg; +} diff --git a/tests/baselines/reference/mappedTypeParameterConstraint.symbols b/tests/baselines/reference/mappedTypeParameterConstraint.symbols new file mode 100644 index 00000000000..1609c465005 --- /dev/null +++ b/tests/baselines/reference/mappedTypeParameterConstraint.symbols @@ -0,0 +1,23 @@ +=== tests/cases/compiler/mappedTypeParameterConstraint.ts === +// Repro for #27596 + +type MyMap = {[P in keyof T]: T[keyof T]}; +>MyMap : Symbol(MyMap, Decl(mappedTypeParameterConstraint.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeParameterConstraint.ts, 2, 11)) +>P : Symbol(P, Decl(mappedTypeParameterConstraint.ts, 2, 18)) +>T : Symbol(T, Decl(mappedTypeParameterConstraint.ts, 2, 11)) +>T : Symbol(T, Decl(mappedTypeParameterConstraint.ts, 2, 11)) +>T : Symbol(T, Decl(mappedTypeParameterConstraint.ts, 2, 11)) + +function foo(arg: U): MyMap { +>foo : Symbol(foo, Decl(mappedTypeParameterConstraint.ts, 2, 45)) +>U : Symbol(U, Decl(mappedTypeParameterConstraint.ts, 3, 13)) +>arg : Symbol(arg, Decl(mappedTypeParameterConstraint.ts, 3, 16)) +>U : Symbol(U, Decl(mappedTypeParameterConstraint.ts, 3, 13)) +>MyMap : Symbol(MyMap, Decl(mappedTypeParameterConstraint.ts, 0, 0)) +>U : Symbol(U, Decl(mappedTypeParameterConstraint.ts, 3, 13)) + + return arg; +>arg : Symbol(arg, Decl(mappedTypeParameterConstraint.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/mappedTypeParameterConstraint.types b/tests/baselines/reference/mappedTypeParameterConstraint.types new file mode 100644 index 00000000000..54af46ecfcf --- /dev/null +++ b/tests/baselines/reference/mappedTypeParameterConstraint.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/mappedTypeParameterConstraint.ts === +// Repro for #27596 + +type MyMap = {[P in keyof T]: T[keyof T]}; +>MyMap : MyMap + +function foo(arg: U): MyMap { +>foo : (arg: U) => MyMap +>arg : U + + return arg; +>arg : U +} + diff --git a/tests/cases/compiler/mappedTypeParameterConstraint.ts b/tests/cases/compiler/mappedTypeParameterConstraint.ts new file mode 100644 index 00000000000..16b37999c92 --- /dev/null +++ b/tests/cases/compiler/mappedTypeParameterConstraint.ts @@ -0,0 +1,6 @@ +// Repro for #27596 + +type MyMap = {[P in keyof T]: T[keyof T]}; +function foo(arg: U): MyMap { + return arg; +}