mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 15:45:27 -05:00
Properly compute lower bound of key type in a mapped type
This commit is contained in:
@@ -7084,6 +7084,39 @@ namespace ts {
|
||||
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, undefined);
|
||||
}
|
||||
|
||||
// Return the lower bound of the key type in a mapped type. Intuitively, the lower
|
||||
// bound includes those keys that are known to always be present, for example because
|
||||
// because of constraints on type parameters (e.g. 'keyof T' for a constrained T).
|
||||
function getLowerBoundOfKeyType(type: Type): Type {
|
||||
if (type.flags & (TypeFlags.Any | TypeFlags.Primitive)) {
|
||||
return type;
|
||||
}
|
||||
if (type.flags & TypeFlags.Index) {
|
||||
return getIndexType(getApparentType((<IndexType>type).type));
|
||||
}
|
||||
if (type.flags & TypeFlags.Conditional) {
|
||||
return getLowerBoundOfConditionalType(<ConditionalType>type);
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(sameMap((<UnionType>type).types, getLowerBoundOfKeyType));
|
||||
}
|
||||
return neverType;
|
||||
}
|
||||
|
||||
function getLowerBoundOfConditionalType(type: ConditionalType) {
|
||||
if (type.root.isDistributive) {
|
||||
const constraint = getLowerBoundOfKeyType(type.checkType);
|
||||
if (constraint !== type.checkType) {
|
||||
const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
|
||||
return getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/** Resolve the members of a mapped type { [P in K]: T } */
|
||||
function resolveMappedTypeMembers(type: MappedType) {
|
||||
const members: SymbolTable = createSymbolTable();
|
||||
@@ -7112,10 +7145,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X.
|
||||
// Then iterate over the constituents of the key type.
|
||||
const iterationType = constraintType.flags & TypeFlags.Index ? getIndexType(getApparentType((<IndexType>constraintType).type)) : constraintType;
|
||||
forEachType(iterationType, addMemberForKeyType);
|
||||
forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType);
|
||||
}
|
||||
setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user