@@ -7084,6 +7084,39 @@ namespace ts {
70847084 setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
70857085 }
70867086
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+
70877120 /** Resolve the members of a mapped type { [P in K]: T } */
70887121 function resolveMappedTypeMembers(type: MappedType) {
70897122 const members: SymbolTable = createSymbolTable();
@@ -7112,10 +7145,7 @@ namespace ts {
71127145 }
71137146 }
71147147 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);
71197149 }
71207150 setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
71217151
0 commit comments