@@ -4536,15 +4536,27 @@ namespace ts {
45364536 const typeParameter = getTypeParameterFromMappedType(type);
45374537 const constraintType = getConstraintTypeFromMappedType(type);
45384538 const templateType = getTemplateTypeFromMappedType(type);
4539- const modifiersType = getModifiersTypeFromMappedType(type);
4539+ const modifiersType = getApparentType( getModifiersTypeFromMappedType(type) );
45404540 const templateReadonly = !!type.declaration.readonlyToken;
45414541 const templateOptional = !!type.declaration.questionToken;
4542- // First, if the constraint type is a type parameter, obtain the base constraint. Then,
4543- // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
4544- // Finally, iterate over the constituents of the resulting iteration type.
4545- const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentType(constraintType) : constraintType;
4546- const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType;
4547- forEachType(iterationType, t => {
4542+ if (type.declaration.typeParameter.constraint.kind === SyntaxKind.TypeOperator) {
4543+ // We have a { [P in keyof T]: X }
4544+ forEachType(getLiteralTypeFromPropertyNames(modifiersType), addMemberForKeyType);
4545+ if (getIndexInfoOfType(modifiersType, IndexKind.String)) {
4546+ addMemberForKeyType(stringType);
4547+ }
4548+ }
4549+ else {
4550+ // First, if the constraint type is a type parameter, obtain the base constraint. Then,
4551+ // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
4552+ // Finally, iterate over the constituents of the resulting iteration type.
4553+ const keyType = constraintType.flags & TypeFlags.TypeVariable ? getApparentType(constraintType) : constraintType;
4554+ const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>keyType).type)) : keyType;
4555+ forEachType(iterationType, addMemberForKeyType);
4556+ }
4557+ setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
4558+
4559+ function addMemberForKeyType(t: Type) {
45484560 // Create a mapper from T to the current iteration type constituent. Then, if the
45494561 // mapped type is itself an instantiated type, combine the iteration mapper with the
45504562 // instantiation mapper.
@@ -4565,8 +4577,7 @@ namespace ts {
45654577 else if (t.flags & TypeFlags.String) {
45664578 stringIndexInfo = createIndexInfo(propType, templateReadonly);
45674579 }
4568- });
4569- setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
4580+ }
45704581 }
45714582
45724583 function getTypeParameterFromMappedType(type: MappedType) {
0 commit comments