@@ -17493,30 +17493,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
17493
17493
return constraintType;
17494
17494
}
17495
17495
const keyTypes: Type[] = [];
17496
- if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
17497
- // We have a { [P in keyof T]: X }
17498
-
17499
- // `getApparentType` on the T in a generic mapped type can trigger a circularity
17500
- // (conditionals and `infer` types create a circular dependency in the constraint resolution)
17501
- // so we only eagerly manifest the keys if the constraint is nongeneric
17502
- if (!isGenericIndexType(constraintType)) {
17503
- const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
17504
- forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, !!(indexFlags & IndexFlags.StringsOnly), addMemberForKeyType);
17505
- }
17506
- else {
17507
- // we have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer the whole `keyof whatever` for later
17508
- // since it's not safe to resolve the shape of modifier type
17496
+ // Calling getApparentType on the `T` of a `keyof T` in the constraint type of a generic mapped type can
17497
+ // trigger a circularity. For example, `T extends { [P in keyof T & string as Captitalize<P>]: any }` is
17498
+ // a circular definition. For this reason, we only eagerly manifest the keys if the constraint is non-generic.
17499
+ if (isGenericIndexType(constraintType)) {
17500
+ if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
17501
+ // We have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer
17502
+ // the whole `keyof whatever` for later since it's not safe to resolve the shape of modifier type.
17509
17503
return getIndexTypeForGenericType(type, indexFlags);
17510
17504
}
17505
+ // Include the generic component in the resulting type.
17506
+ forEachType(constraintType, addMemberForKeyType);
17507
+ }
17508
+ else if (isMappedTypeWithKeyofConstraintDeclaration(type)) {
17509
+ const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T'
17510
+ forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, !!(indexFlags & IndexFlags.StringsOnly), addMemberForKeyType);
17511
17511
}
17512
17512
else {
17513
17513
forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
17514
17514
}
17515
- if (isGenericIndexType(constraintType)) { // include the generic component in the resulting type
17516
- forEachType(constraintType, addMemberForKeyType);
17517
- }
17518
- // we had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the original constraintType,
17519
- // so we can return the union that preserves aliases/origin data if possible
17515
+ // We had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the
17516
+ // original constraintType, so we can return the union that preserves aliases/origin data if possible.
17520
17517
const result = indexFlags & IndexFlags.NoIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) : getUnionType(keyTypes);
17521
17518
if (result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types)) {
17522
17519
return constraintType;
0 commit comments