@@ -7084,6 +7084,39 @@ namespace ts {
7084
7084
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
7085
7085
}
7086
7086
7087
+ // Return the lower bound of the key type in a mapped type. Intuitively, the lower
7088
+ // bound includes those keys that are known to always be present, for example because
7089
+ // because of constraints on type parameters (e.g. 'keyof T' for a constrained T).
7090
+ function getLowerBoundOfKeyType(type: Type): Type {
7091
+ if (type.flags & (TypeFlags.Any | TypeFlags.Primitive)) {
7092
+ return type;
7093
+ }
7094
+ if (type.flags & TypeFlags.Index) {
7095
+ return getIndexType(getApparentType((<IndexType>type).type));
7096
+ }
7097
+ if (type.flags & TypeFlags.Conditional) {
7098
+ return getLowerBoundOfConditionalType(<ConditionalType>type);
7099
+ }
7100
+ if (type.flags & TypeFlags.Union) {
7101
+ return getUnionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
7102
+ }
7103
+ if (type.flags & TypeFlags.Intersection) {
7104
+ return getIntersectionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
7105
+ }
7106
+ return neverType;
7107
+ }
7108
+
7109
+ function getLowerBoundOfConditionalType(type: ConditionalType) {
7110
+ if (type.root.isDistributive) {
7111
+ const constraint = getLowerBoundOfKeyType(type.checkType);
7112
+ if (constraint !== type.checkType) {
7113
+ const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
7114
+ return getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
7115
+ }
7116
+ }
7117
+ return type;
7118
+ }
7119
+
7087
7120
/** Resolve the members of a mapped type { [P in K]: T } */
7088
7121
function resolveMappedTypeMembers(type: MappedType) {
7089
7122
const members: SymbolTable = createSymbolTable();
@@ -7112,10 +7145,7 @@ namespace ts {
7112
7145
}
7113
7146
}
7114
7147
else {
7115
- // If the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
7116
- // Then iterate over the constituents of the key type.
7117
- const iterationType = constraintType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>constraintType).type)) : constraintType;
7118
- forEachType(iterationType, addMemberForKeyType);
7148
+ forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
7119
7149
}
7120
7150
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
7121
7151
0 commit comments