Skip to content

Commit 8b4744a

Browse files
committed
Allow deeply nested immediately resolving conditionals without any syntactic requirements or implementation contortions
Extract logic into function
1 parent 8fe8284 commit 8b4744a

File tree

5 files changed

+665
-4
lines changed

5 files changed

+665
-4
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12767,26 +12767,26 @@ namespace ts {
1276712767
// We attempt to resolve the conditional type only when the check and extends types are non-generic
1276812768
if (!checkTypeInstantiable && !isGenericObjectType(inferredExtendsType) && !isGenericIndexType(inferredExtendsType)) {
1276912769
if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) {
12770-
return instantiateType(root.trueType, combinedMapper || mapper);
12770+
return instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper);
1277112771
}
1277212772
// Return union of trueType and falseType for 'any' since it matches anything
1277312773
if (checkType.flags & TypeFlags.Any) {
12774-
return getUnionType([instantiateType(root.trueType, combinedMapper || mapper), instantiateType(root.falseType, mapper)]);
12774+
return getUnionType([instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper), instantiateTypeWithoutDepthIncrease(root.falseType, mapper)]);
1277512775
}
1277612776
// Return falseType for a definitely false extends check. We check an instantiations of the two
1277712777
// types with type parameters mapped to the wildcard type, the most permissive instantiations
1277812778
// possible (the wildcard type is assignable to and from all types). If those are not related,
1277912779
// then no instantiations will be and we can just return the false branch type.
1278012780
if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) {
12781-
return instantiateType(root.falseType, mapper);
12781+
return instantiateTypeWithoutDepthIncrease(root.falseType, mapper);
1278212782
}
1278312783
// Return trueType for a definitely true extends check. We check instantiations of the two
1278412784
// types with type parameters mapped to their restrictive form, i.e. a form of the type parameter
1278512785
// that has no constraint. This ensures that, for example, the type
1278612786
// type Foo<T extends { x: any }> = T extends { x: string } ? string : number
1278712787
// doesn't immediately resolve to 'string' instead of being deferred.
1278812788
if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) {
12789-
return instantiateType(root.trueType, combinedMapper || mapper);
12789+
return instantiateTypeWithoutDepthIncrease(root.trueType, combinedMapper || mapper);
1279012790
}
1279112791
}
1279212792
// Return a deferred type for a check that is neither definitely true nor definitely false
@@ -13771,6 +13771,17 @@ namespace ts {
1377113771
return result;
1377213772
}
1377313773

13774+
/**
13775+
* This can be used to avoid the penalty on instantiation depth for types which result from immediate
13776+
* simplification. It essentially removes the depth increase done in `instantiateType`.
13777+
*/
13778+
function instantiateTypeWithoutDepthIncrease(type: Type, mapper: TypeMapper | undefined) {
13779+
instantiationDepth--;
13780+
const result = instantiateType(type, mapper);
13781+
instantiationDepth++;
13782+
return result;
13783+
}
13784+
1377413785
function instantiateTypeWorker(type: Type, mapper: TypeMapper): Type {
1377513786
const flags = type.flags;
1377613787
if (flags & TypeFlags.TypeParameter) {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
//// [deeplyNestedConditionalTypes.ts]
2+
type Foo<T> =
3+
T extends 0 ? '0' :
4+
T extends 1 ? '1' :
5+
T extends 2 ? '2' :
6+
T extends 3 ? '3' :
7+
T extends 4 ? '4' :
8+
T extends 5 ? '5' :
9+
T extends 6 ? '6' :
10+
T extends 7 ? '7' :
11+
T extends 8 ? '8' :
12+
T extends 9 ? '9' :
13+
T extends 10 ? '10' :
14+
T extends 11 ? '11' :
15+
T extends 12 ? '12' :
16+
T extends 13 ? '13' :
17+
T extends 14 ? '14' :
18+
T extends 15 ? '15' :
19+
T extends 16 ? '16' :
20+
T extends 17 ? '17' :
21+
T extends 18 ? '18' :
22+
T extends 19 ? '19' :
23+
T extends 20 ? '20' :
24+
T extends 21 ? '21' :
25+
T extends 22 ? '22' :
26+
T extends 23 ? '23' :
27+
T extends 24 ? '24' :
28+
T extends 25 ? '25' :
29+
T extends 26 ? '26' :
30+
T extends 27 ? '27' :
31+
T extends 28 ? '28' :
32+
T extends 29 ? '29' :
33+
T extends 30 ? '30' :
34+
T extends 31 ? '31' :
35+
T extends 32 ? '32' :
36+
T extends 33 ? '33' :
37+
T extends 34 ? '34' :
38+
T extends 35 ? '35' :
39+
T extends 36 ? '36' :
40+
T extends 37 ? '37' :
41+
T extends 38 ? '38' :
42+
T extends 39 ? '39' :
43+
T extends 40 ? '40' :
44+
T extends 41 ? '41' :
45+
T extends 42 ? '42' :
46+
T extends 43 ? '43' :
47+
T extends 44 ? '44' :
48+
T extends 45 ? '45' :
49+
T extends 46 ? '46' :
50+
T extends 47 ? '47' :
51+
T extends 48 ? '48' :
52+
T extends 49 ? '49' :
53+
T extends 50 ? '50' :
54+
T extends 51 ? '51' :
55+
T extends 52 ? '52' :
56+
T extends 53 ? '53' :
57+
T extends 54 ? '54' :
58+
T extends 55 ? '55' :
59+
T extends 56 ? '56' :
60+
T extends 57 ? '57' :
61+
T extends 58 ? '58' :
62+
T extends 59 ? '59' :
63+
T extends 60 ? '60' :
64+
T extends 61 ? '61' :
65+
T extends 62 ? '62' :
66+
T extends 63 ? '63' :
67+
T extends 64 ? '64' :
68+
T extends 65 ? '65' :
69+
T extends 66 ? '66' :
70+
T extends 67 ? '67' :
71+
T extends 68 ? '68' :
72+
T extends 69 ? '69' :
73+
T extends 70 ? '70' :
74+
T extends 71 ? '71' :
75+
T extends 72 ? '72' :
76+
T extends 73 ? '73' :
77+
T extends 74 ? '74' :
78+
T extends 75 ? '75' :
79+
T extends 76 ? '76' :
80+
T extends 77 ? '77' :
81+
T extends 78 ? '78' :
82+
T extends 79 ? '79' :
83+
T extends 80 ? '80' :
84+
T extends 81 ? '81' :
85+
T extends 82 ? '82' :
86+
T extends 83 ? '83' :
87+
T extends 84 ? '84' :
88+
T extends 85 ? '85' :
89+
T extends 86 ? '86' :
90+
T extends 87 ? '87' :
91+
T extends 88 ? '88' :
92+
T extends 89 ? '89' :
93+
T extends 90 ? '90' :
94+
T extends 91 ? '91' :
95+
T extends 92 ? '92' :
96+
T extends 93 ? '93' :
97+
T extends 94 ? '94' :
98+
T extends 95 ? '95' :
99+
T extends 96 ? '96' :
100+
T extends 97 ? '97' :
101+
T extends 98 ? '98' :
102+
T extends 99 ? '99' :
103+
never;
104+
105+
type T0 = Foo<99>;
106+
type T1 = Foo<any>;
107+
108+
//// [deeplyNestedConditionalTypes.js]
109+
"use strict";
110+
111+
112+
//// [deeplyNestedConditionalTypes.d.ts]
113+
declare type Foo<T> = T extends 0 ? '0' : T extends 1 ? '1' : T extends 2 ? '2' : T extends 3 ? '3' : T extends 4 ? '4' : T extends 5 ? '5' : T extends 6 ? '6' : T extends 7 ? '7' : T extends 8 ? '8' : T extends 9 ? '9' : T extends 10 ? '10' : T extends 11 ? '11' : T extends 12 ? '12' : T extends 13 ? '13' : T extends 14 ? '14' : T extends 15 ? '15' : T extends 16 ? '16' : T extends 17 ? '17' : T extends 18 ? '18' : T extends 19 ? '19' : T extends 20 ? '20' : T extends 21 ? '21' : T extends 22 ? '22' : T extends 23 ? '23' : T extends 24 ? '24' : T extends 25 ? '25' : T extends 26 ? '26' : T extends 27 ? '27' : T extends 28 ? '28' : T extends 29 ? '29' : T extends 30 ? '30' : T extends 31 ? '31' : T extends 32 ? '32' : T extends 33 ? '33' : T extends 34 ? '34' : T extends 35 ? '35' : T extends 36 ? '36' : T extends 37 ? '37' : T extends 38 ? '38' : T extends 39 ? '39' : T extends 40 ? '40' : T extends 41 ? '41' : T extends 42 ? '42' : T extends 43 ? '43' : T extends 44 ? '44' : T extends 45 ? '45' : T extends 46 ? '46' : T extends 47 ? '47' : T extends 48 ? '48' : T extends 49 ? '49' : T extends 50 ? '50' : T extends 51 ? '51' : T extends 52 ? '52' : T extends 53 ? '53' : T extends 54 ? '54' : T extends 55 ? '55' : T extends 56 ? '56' : T extends 57 ? '57' : T extends 58 ? '58' : T extends 59 ? '59' : T extends 60 ? '60' : T extends 61 ? '61' : T extends 62 ? '62' : T extends 63 ? '63' : T extends 64 ? '64' : T extends 65 ? '65' : T extends 66 ? '66' : T extends 67 ? '67' : T extends 68 ? '68' : T extends 69 ? '69' : T extends 70 ? '70' : T extends 71 ? '71' : T extends 72 ? '72' : T extends 73 ? '73' : T extends 74 ? '74' : T extends 75 ? '75' : T extends 76 ? '76' : T extends 77 ? '77' : T extends 78 ? '78' : T extends 79 ? '79' : T extends 80 ? '80' : T extends 81 ? '81' : T extends 82 ? '82' : T extends 83 ? '83' : T extends 84 ? '84' : T extends 85 ? '85' : T extends 86 ? '86' : T extends 87 ? '87' : T extends 88 ? '88' : T extends 89 ? '89' : T extends 90 ? '90' : T extends 91 ? '91' : T extends 92 ? '92' : T extends 93 ? '93' : T extends 94 ? '94' : T extends 95 ? '95' : T extends 96 ? '96' : T extends 97 ? '97' : T extends 98 ? '98' : T extends 99 ? '99' : never;
114+
declare type T0 = Foo<99>;
115+
declare type T1 = Foo<any>;

0 commit comments

Comments
 (0)