Skip to content

Commit

Permalink
When instantiating a mapped type, clone the type parameter. (#27597)
Browse files Browse the repository at this point in the history
This gives the type parameter returned by getTypeParameterFromMappedType
an accurate constraint.

Fixes #27596.
  • Loading branch information
mattmccutchen authored and weswigham committed Oct 11, 2018
1 parent 4d504f9 commit d19fb98
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -10413,6 +10413,12 @@ namespace ts {
const result = <AnonymousType>createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol);
if (type.objectFlags & ObjectFlags.Mapped) {
(<MappedType>result).declaration = (<MappedType>type).declaration;
// C.f. instantiateSignature
const origTypeParameter = getTypeParameterFromMappedType(<MappedType>type);
const freshTypeParameter = cloneTypeParameter(origTypeParameter);
(<MappedType>result).typeParameter = freshTypeParameter;
mapper = combineTypeMappers(makeUnaryTypeMapper(origTypeParameter, freshTypeParameter), mapper);
freshTypeParameter.mapper = mapper;
}
result.target = type;
result.mapper = mapper;
Expand Down
14 changes: 14 additions & 0 deletions tests/baselines/reference/mappedTypeParameterConstraint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//// [mappedTypeParameterConstraint.ts]
// Repro for #27596

type MyMap<T> = {[P in keyof T]: T[keyof T]};
function foo<U>(arg: U): MyMap<U> {
return arg;
}


//// [mappedTypeParameterConstraint.js]
// Repro for #27596
function foo(arg) {
return arg;
}
23 changes: 23 additions & 0 deletions tests/baselines/reference/mappedTypeParameterConstraint.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== tests/cases/compiler/mappedTypeParameterConstraint.ts ===
// Repro for #27596

type MyMap<T> = {[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<U>(arg: U): MyMap<U> {
>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))
}

14 changes: 14 additions & 0 deletions tests/baselines/reference/mappedTypeParameterConstraint.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=== tests/cases/compiler/mappedTypeParameterConstraint.ts ===
// Repro for #27596

type MyMap<T> = {[P in keyof T]: T[keyof T]};
>MyMap : MyMap<T>

function foo<U>(arg: U): MyMap<U> {
>foo : <U>(arg: U) => MyMap<U>
>arg : U

return arg;
>arg : U
}

6 changes: 6 additions & 0 deletions tests/cases/compiler/mappedTypeParameterConstraint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Repro for #27596

type MyMap<T> = {[P in keyof T]: T[keyof T]};
function foo<U>(arg: U): MyMap<U> {
return arg;
}

0 comments on commit d19fb98

Please sign in to comment.