Skip to content

Commit 055c0af

Browse files
authored
Merge pull request #12843 from Microsoft/mappedTypeModifiers3
Additional tweak to mapped type property modifier propagation
2 parents d050673 + 4898b9e commit 055c0af

File tree

5 files changed

+256
-144
lines changed

5 files changed

+256
-144
lines changed

src/compiler/checker.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,12 +4590,22 @@ namespace ts {
45904590

45914591
function getModifiersTypeFromMappedType(type: MappedType) {
45924592
if (!type.modifiersType) {
4593-
// If the mapped type was declared as { [P in keyof T]: X } or as { [P in K]: X }, where
4594-
// K is constrained to 'K extends keyof T', then we will copy property modifiers from T.
4595-
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4596-
const constraint = getConstraintTypeFromMappedType(declaredType);
4597-
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4598-
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4593+
const constraintDeclaration = type.declaration.typeParameter.constraint;
4594+
if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
4595+
// If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
4596+
// AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
4597+
// 'keyof T' to a literal union type and we can't recover T from that type.
4598+
type.modifiersType = instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraintDeclaration).type), type.mapper || identityMapper);
4599+
}
4600+
else {
4601+
// Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
4602+
// get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
4603+
// the modifiers type is T. Otherwise, the modifiers type is {}.
4604+
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4605+
const constraint = getConstraintTypeFromMappedType(declaredType);
4606+
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4607+
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4608+
}
45994609
}
46004610
return type.modifiersType;
46014611
}

tests/baselines/reference/mappedTypeModifiers.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,22 @@ var v01: Pick<Pick<T, keyof T>, keyof T>;
1919
var v02: TP;
2020
var v02: { [P in keyof T]?: T[P] };
2121
var v02: Partial<T>;
22-
var v02: Pick<TP, keyof T>;
22+
var v02: { [P in keyof TP]: TP[P] }
23+
var v02: Pick<TP, keyof TP>;
2324

2425
var v03: TR;
2526
var v03: { readonly [P in keyof T]: T[P] };
2627
var v03: Readonly<T>;
27-
var v03: Pick<TR, keyof T>;
28+
var v03: { [P in keyof TR]: TR[P] }
29+
var v03: Pick<TR, keyof TR>;
2830

2931
var v04: TPR;
3032
var v04: { readonly [P in keyof T]?: T[P] };
3133
var v04: Partial<TR>;
3234
var v04: Readonly<TP>;
3335
var v04: Partial<Readonly<T>>;
3436
var v04: Readonly<Partial<T>>;
37+
var v04: { [P in keyof TPR]: TPR[P] }
3538
var v04: Pick<TPR, keyof T>;
3639

3740
type Boxified<T> = { [P in keyof T]: { x: T[P] } };
@@ -55,20 +58,23 @@ var b01: Pick<Pick<B, keyof B>, keyof B>;
5558
var b02: BP;
5659
var b02: { [P in keyof B]?: B[P] };
5760
var b02: Partial<B>;
58-
var b02: Pick<BP, keyof B>;
61+
var b02: { [P in keyof BP]: BP[P] }
62+
var b02: Pick<BP, keyof BP>;
5963

6064
var b03: BR;
6165
var b03: { readonly [P in keyof B]: B[P] };
6266
var b03: Readonly<B>;
63-
var b03: Pick<BR, keyof B>;
67+
var b03: { [P in keyof BR]: BR[P] }
68+
var b03: Pick<BR, keyof BR>;
6469

6570
var b04: BPR;
6671
var b04: { readonly [P in keyof B]?: B[P] };
6772
var b04: Partial<BR>;
6873
var b04: Readonly<BP>;
6974
var b04: Partial<Readonly<B>>;
7075
var b04: Readonly<Partial<B>>;
71-
var b04: Pick<BPR, keyof B>;
76+
var b04: { [P in keyof BPR]: BPR[P] }
77+
var b04: Pick<BPR, keyof BPR>;
7278

7379
//// [mappedTypeModifiers.js]
7480
var v00;
@@ -84,6 +90,8 @@ var v02;
8490
var v02;
8591
var v02;
8692
var v02;
93+
var v02;
94+
var v03;
8795
var v03;
8896
var v03;
8997
var v03;
@@ -95,6 +103,7 @@ var v04;
95103
var v04;
96104
var v04;
97105
var v04;
106+
var v04;
98107
var b00;
99108
var b00;
100109
var b00;
@@ -108,6 +117,8 @@ var b02;
108117
var b02;
109118
var b02;
110119
var b02;
120+
var b02;
121+
var b03;
111122
var b03;
112123
var b03;
113124
var b03;
@@ -119,3 +130,4 @@ var b04;
119130
var b04;
120131
var b04;
121132
var b04;
133+
var b04;

0 commit comments

Comments
 (0)