@@ -15848,6 +15848,19 @@ namespace ts {
15848
15848
// Eagerly resolve the constraint type which forces an error if the constraint type circularly
15849
15849
// references itself through one or more type aliases.
15850
15850
getConstraintTypeFromMappedType(type);
15851
+ // Detect if the mapped type should be homomorphic to a tuple by checking the declaration of the constraint if it contains a keyof over a tuple
15852
+ if (node.typeParameter.constraint && isTypeOperatorNode(node.typeParameter.constraint) && node.typeParameter.constraint.operator === SyntaxKind.KeyOfKeyword) {
15853
+ const keyOfTarget = getTypeFromTypeNode(node.typeParameter.constraint.type);
15854
+ if (isTupleType(keyOfTarget)) {
15855
+ // Instantiate the mapped type over a tuple with an identity mapper
15856
+ const instantiatedTupleMappedType = instantiateMappedTupleType(
15857
+ keyOfTarget,
15858
+ type,
15859
+ makeFunctionTypeMapper(identity)
15860
+ );
15861
+ links.resolvedType = instantiatedTupleMappedType;
15862
+ }
15863
+ }
15851
15864
}
15852
15865
return links.resolvedType;
15853
15866
}
@@ -35579,14 +35592,17 @@ namespace ts {
35579
35592
reportImplicitAny(node, anyType);
35580
35593
}
35581
35594
35582
- const type = getTypeFromMappedTypeNode(node) as MappedType;
35583
- const nameType = getNameTypeFromMappedType(type);
35584
- if (nameType) {
35585
- checkTypeAssignableTo(nameType, keyofConstraintType, node.nameType);
35586
- }
35587
- else {
35588
- const constraintType = getConstraintTypeFromMappedType(type);
35589
- checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter));
35595
+ const type = getTypeFromMappedTypeNode(node);
35596
+ // Continue to check if the type returned is a mapped type, that means it wasn't resolved to a homomorphic tuple type
35597
+ if (type.flags & TypeFlags.Object && (type as ObjectType).objectFlags & ObjectFlags.Mapped) {
35598
+ const nameType = getNameTypeFromMappedType(type as MappedType);
35599
+ if (nameType) {
35600
+ checkTypeAssignableTo(nameType, keyofConstraintType, node.nameType);
35601
+ }
35602
+ else {
35603
+ const constraintType = getConstraintTypeFromMappedType(type as MappedType);
35604
+ checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter));
35605
+ }
35590
35606
}
35591
35607
}
35592
35608
0 commit comments