mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 05:17:43 -05:00
Check nested conditional types for non-distributiveness in mapped types with 'as' clauses (#41713)
* Check nested conditional types for non-distributiveness * Rename to maybeNonDistributiveNameType * Add regression test
This commit is contained in:
@@ -13547,17 +13547,17 @@ namespace ts {
|
||||
constraint;
|
||||
}
|
||||
|
||||
// Ordinarily we reduce a keyof M where M is a mapped type { [P in K as N<P>]: X } to simply N<K>. This however presumes
|
||||
// that N distributes over union types, i.e. that N<A | B | C> is equivalent to N<A> | N<B> | N<C>. That presumption is
|
||||
// generally true, except when N is a non-distributive conditional type or an instantiable type with non-distributive
|
||||
// conditional type as a constituent. In those cases, we cannot reduce keyof M and need to preserve it as is.
|
||||
function isNonDistributiveNameType(type: Type | undefined): boolean {
|
||||
// Ordinarily we reduce a keyof M, where M is a mapped type { [P in K as N<P>]: X }, to simply N<K>. This however presumes
|
||||
// that N distributes over union types, i.e. that N<A | B | C> is equivalent to N<A> | N<B> | N<C>. That presumption may not
|
||||
// be true when N is a non-distributive conditional type or an instantiable type with a non-distributive conditional type as
|
||||
// a constituent. In those cases, we cannot reduce keyof M and need to preserve it as is.
|
||||
function maybeNonDistributiveNameType(type: Type | undefined): boolean {
|
||||
return !!(type && (
|
||||
type.flags & TypeFlags.Conditional && !(<ConditionalType>type).root.isDistributive ||
|
||||
type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) && some((<UnionOrIntersectionType | TemplateLiteralType>type).types, isNonDistributiveNameType) ||
|
||||
type.flags & (TypeFlags.Index | TypeFlags.StringMapping) && isNonDistributiveNameType((<IndexType | StringMappingType>type).type) ||
|
||||
type.flags & TypeFlags.IndexedAccess && isNonDistributiveNameType((<IndexedAccessType>type).indexType) ||
|
||||
type.flags & TypeFlags.Substitution && isNonDistributiveNameType((<SubstitutionType>type).substitute)));
|
||||
type.flags & TypeFlags.Conditional && (!(<ConditionalType>type).root.isDistributive || maybeNonDistributiveNameType((<ConditionalType>type).checkType)) ||
|
||||
type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) && some((<UnionOrIntersectionType | TemplateLiteralType>type).types, maybeNonDistributiveNameType) ||
|
||||
type.flags & (TypeFlags.Index | TypeFlags.StringMapping) && maybeNonDistributiveNameType((<IndexType | StringMappingType>type).type) ||
|
||||
type.flags & TypeFlags.IndexedAccess && maybeNonDistributiveNameType((<IndexedAccessType>type).indexType) ||
|
||||
type.flags & TypeFlags.Substitution && maybeNonDistributiveNameType((<SubstitutionType>type).substitute)));
|
||||
}
|
||||
|
||||
function getLiteralTypeFromPropertyName(name: PropertyName) {
|
||||
@@ -13607,7 +13607,7 @@ namespace ts {
|
||||
type = getReducedType(type);
|
||||
return type.flags & TypeFlags.Union ? getIntersectionType(map((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
|
||||
type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) :
|
||||
type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || isGenericMappedType(type) && isNonDistributiveNameType(getNameTypeFromMappedType(type)) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, stringsOnly) :
|
||||
type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || isGenericMappedType(type) && maybeNonDistributiveNameType(getNameTypeFromMappedType(type)) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, stringsOnly) :
|
||||
getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(<MappedType>type, noIndexSignatures) :
|
||||
type === wildcardType ? wildcardType :
|
||||
type.flags & TypeFlags.Unknown ? neverType :
|
||||
|
||||
Reference in New Issue
Block a user