@@ -14567,16 +14567,33 @@ namespace ts {
14567
14567
return type;
14568
14568
}
14569
14569
14570
+ function isTypicalNondistributiveConditional(root: ConditionalRoot) {
14571
+ return !root.isDistributive
14572
+ && root.node.checkType.kind === SyntaxKind.TupleType
14573
+ && length((root.node.checkType as TupleTypeNode).elements) === 1
14574
+ && root.node.extendsType.kind === SyntaxKind.TupleType
14575
+ && length((root.node.extendsType as TupleTypeNode).elements) === 1;
14576
+ }
14577
+
14578
+ /**
14579
+ * We syntactually check for common nondistributive conditional shapes and unwrap them into
14580
+ * the intended comparison - we do this so we can check if the unwrapped types are generic or
14581
+ * not and appropriately defer condition calculation
14582
+ */
14583
+ function unwrapNondistributiveConditionalTuple(root: ConditionalRoot, type: Type) {
14584
+ return isTypicalNondistributiveConditional(root) && isTupleType(type) ? getTypeArguments(type)[0] : type;
14585
+ }
14586
+
14570
14587
function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
14571
14588
let result;
14572
14589
let extraTypes: Type[] | undefined;
14573
14590
// We loop here for an immediately nested conditional type in the false position, effectively treating
14574
14591
// types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for
14575
14592
// purposes of resolution. This means such types aren't subject to the instatiation depth limiter.
14576
14593
while (true) {
14577
- const checkType = instantiateType(root.checkType, mapper);
14594
+ const checkType = instantiateType(unwrapNondistributiveConditionalTuple( root, root .checkType) , mapper);
14578
14595
const checkTypeInstantiable = isGenericObjectType(checkType) || isGenericIndexType(checkType);
14579
- const extendsType = instantiateType(root.extendsType, mapper);
14596
+ const extendsType = instantiateType(unwrapNondistributiveConditionalTuple( root, root .extendsType) , mapper);
14580
14597
if (checkType === wildcardType || extendsType === wildcardType) {
14581
14598
return wildcardType;
14582
14599
}
@@ -14599,9 +14616,9 @@ namespace ts {
14599
14616
// types with type parameters mapped to the wildcard type, the most permissive instantiations
14600
14617
// possible (the wildcard type is assignable to and from all types). If those are not related,
14601
14618
// then no instantiations will be and we can just return the false branch type.
14602
- if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && (checkType.flags & TypeFlags.Any || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
14619
+ if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && (( checkType.flags & TypeFlags.Any && root.isDistributive) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
14603
14620
// Return union of trueType and falseType for 'any' since it matches anything
14604
- if (checkType.flags & TypeFlags.Any) {
14621
+ if (checkType.flags & TypeFlags.Any && root.isDistributive ) {
14605
14622
(extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper));
14606
14623
}
14607
14624
// If falseType is an immediately nested conditional type that isn't distributive or has an
@@ -14630,8 +14647,8 @@ namespace ts {
14630
14647
// Return a deferred type for a check that is neither definitely true nor definitely false
14631
14648
result = <ConditionalType>createType(TypeFlags.Conditional);
14632
14649
result.root = root;
14633
- result.checkType = checkType;
14634
- result.extendsType = extendsType;
14650
+ result.checkType = instantiateType(root. checkType, mapper) ;
14651
+ result.extendsType = instantiateType(root. extendsType, mapper) ;
14635
14652
result.mapper = mapper;
14636
14653
result.combinedMapper = combinedMapper;
14637
14654
result.aliasSymbol = aliasSymbol || root.aliasSymbol;
0 commit comments