Skip to content

Commit cd31843

Browse files
committed
Experiment short-circuiting of union distribution
1 parent 71b2ba6 commit cd31843

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

‎src/compiler/checker.ts‎

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17343,16 +17343,45 @@ namespace ts {
1734317343
// Distributive conditional types are distributed over union types. For example, when the
1734417344
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
1734517345
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
17346-
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
17347-
mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
17348-
getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
17346+
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never)
17347+
? root.isDistributive && !isDistributionDependent(root) && !containsInferTypeNode(root.node)
17348+
? getConditionalTypeForSimpleDistributionType(getReducedType(distributionType), (t) => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments)
17349+
: mapTypeWithAlias(getReducedType(distributionType), (t) => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments)
17350+
: getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
1734917351
root.instantiations!.set(id, result);
1735017352
}
1735117353
return result;
1735217354
}
1735317355
return type;
1735417356
}
1735517357

17358+
// For types like A extends B ? C : D, if the check-type (A) appears in neither branch and the extends type (B) has no infer positions,
17359+
// the output type will be combinations of C and D.
17360+
function getConditionalTypeForSimpleDistributionType(type: Type, mapper: (t: Type) => Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type {
17361+
if (!(type.flags & TypeFlags.Union && aliasSymbol)) {
17362+
return mapType(type, mapper);
17363+
}
17364+
let firstMappedType: Type | undefined;
17365+
for(const t of (type as UnionType).types) {
17366+
const mapped = mapper(t);
17367+
if (mapped.flags & TypeFlags.AnyOrUnknown) {
17368+
return mapped;
17369+
}
17370+
else if (!firstMappedType) {
17371+
firstMappedType = mapped;
17372+
}
17373+
else if (firstMappedType !== mapped) {
17374+
return getUnionType([firstMappedType, mapped], UnionReduction.Literal, aliasSymbol, aliasTypeArguments);
17375+
}
17376+
}
17377+
Debug.assertIsDefined(firstMappedType);
17378+
return firstMappedType;
17379+
}
17380+
17381+
function containsInferTypeNode(node: Node) {
17382+
return isInferTypeNode(node) || forEachChildRecursively(node, isInferTypeNode);
17383+
}
17384+
1735617385
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
1735717386
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
1735817387
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {

0 commit comments

Comments
 (0)