Skip to content

Commit 5229176

Browse files
committed
Additional tweak to mapped type property modifier propagation
1 parent 7c5c664 commit 5229176

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

src/compiler/checker.ts

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

45784578
function getModifiersTypeFromMappedType(type: MappedType) {
45794579
if (!type.modifiersType) {
4580-
// If the mapped type was declared as { [P in keyof T]: X } or as { [P in K]: X }, where
4581-
// K is constrained to 'K extends keyof T', then we will copy property modifiers from T.
4582-
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4583-
const constraint = getConstraintTypeFromMappedType(declaredType);
4584-
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4585-
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4580+
const constraintDeclaration = type.declaration.typeParameter.constraint;
4581+
if (constraintDeclaration.kind === SyntaxKind.TypeOperator) {
4582+
// If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check
4583+
// AST nodes here because, when T is a non-generic type, the logic below eagerly resolves
4584+
// 'keyof T' to a literal union type and we can't recover T from that type.
4585+
type.modifiersType = instantiateType(getTypeFromTypeNode((<TypeOperatorNode>constraintDeclaration).type), type.mapper || identityMapper);
4586+
}
4587+
else {
4588+
// Otherwise, get the declared constraint type, and if the constraint type is a type parameter,
4589+
// get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T',
4590+
// the modifiers type is T. Otherwise, the modifiers type is {}.
4591+
const declaredType = <MappedType>getTypeFromMappedTypeNode(type.declaration);
4592+
const constraint = getConstraintTypeFromMappedType(declaredType);
4593+
const extendedConstraint = constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>constraint) : constraint;
4594+
type.modifiersType = extendedConstraint.flags & TypeFlags.Index ? instantiateType((<IndexType>extendedConstraint).type, type.mapper || identityMapper) : emptyObjectType;
4595+
}
45864596
}
45874597
return type.modifiersType;
45884598
}

0 commit comments

Comments
 (0)