New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add heuristic for extracting irreducible null
and undefined
types from intersections of unions
#33150
Add heuristic for extracting irreducible null
and undefined
types from intersections of unions
#33150
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9996,6 +9996,16 @@ namespace ts { | |
return true; | ||
} | ||
|
||
function extractIrreducible(types: Type[], flag: TypeFlags) { | ||
if (every(types, t => !!(t.flags & TypeFlags.Union) && some((t as UnionType).types, tt => !!(tt.flags & flag)))) { | ||
for (let i = 0; i < types.length; i++) { | ||
types[i] = filterType(types[i], t => !(t.flags & flag)); | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
// If the given list of types contains more than one union of primitive types, replace the | ||
// first with a union containing an intersection of those primitive types, then remove the | ||
// other unions and return true. Otherwise, do nothing and return false. | ||
|
@@ -10114,6 +10124,12 @@ namespace ts { | |
// reduced we'll never reduce again, so this occurs at most once. | ||
result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); | ||
} | ||
else if (extractIrreducible(typeSet, TypeFlags.Undefined)) { | ||
result = getUnionType([getIntersectionType(typeSet), undefinedType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't we run both, for large intersections of the form There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we do - note the recursive |
||
} | ||
else if (extractIrreducible(typeSet, TypeFlags.Null)) { | ||
result = getUnionType([getIntersectionType(typeSet), nullType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); | ||
} | ||
else { | ||
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of | ||
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
//// [partialOfLargeAPIIsAbleToBeWorkedWith.ts] | ||
interface MyAPI { | ||
0: (x: 0) => string; | ||
1: (x: 1) => string; | ||
2: (x: 2) => string; | ||
3: (x: 3) => string; | ||
4: (x: 4) => string; | ||
5: (x: 5) => string; | ||
6: (x: 6) => string; | ||
7: (x: 7) => string; | ||
8: (x: 8) => string; | ||
9: (x: 9) => string; | ||
10: (x: 10) => string; | ||
11: (x: 11) => string; | ||
12: (x: 12) => string; | ||
13: (x: 13) => string; | ||
14: (x: 14) => string; | ||
15: (x: 15) => string; | ||
16: (x: 16) => string; | ||
17: (x: 17) => string; | ||
18: (x: 18) => string; | ||
19: (x: 19) => string; | ||
20: (x: 20) => string; | ||
21: (x: 21) => string; | ||
22: (x: 22) => string; | ||
23: (x: 23) => string; | ||
24: (x: 24) => string; | ||
25: (x: 25) => string; | ||
26: (x: 26) => string; | ||
27: (x: 27) => string; | ||
28: (x: 28) => string; | ||
29: (x: 29) => string; | ||
30: (x: 30) => string; | ||
31: (x: 31) => string; | ||
32: (x: 32) => string; | ||
33: (x: 33) => string; | ||
34: (x: 34) => string; | ||
35: (x: 35) => string; | ||
36: (x: 36) => string; | ||
37: (x: 37) => string; | ||
38: (x: 38) => string; | ||
39: (x: 39) => string; | ||
40: (x: 40) => string; | ||
41: (x: 41) => string; | ||
42: (x: 42) => string; | ||
43: (x: 43) => string; | ||
44: (x: 44) => string; | ||
45: (x: 45) => string; | ||
46: (x: 46) => string; | ||
47: (x: 47) => string; | ||
48: (x: 48) => string; | ||
49: (x: 49) => string; | ||
50: (x: 50) => string; | ||
51: (x: 51) => string; | ||
} | ||
|
||
const obj: Partial<MyAPI> = {}; | ||
|
||
declare var keys: (keyof MyAPI)[]; | ||
|
||
for (const k of keys) { | ||
obj[k] = () => "12"; // shouldn't cause a complexity error | ||
} | ||
|
||
type PartialNull<T> = {[K in keyof T]?: T[K] | null}; | ||
|
||
const obj2: PartialNull<MyAPI> = {}; | ||
|
||
for (const k of keys) { | ||
obj2[k] = () => "12"; // shouldn't cause a complexity error | ||
} | ||
|
||
|
||
//// [partialOfLargeAPIIsAbleToBeWorkedWith.js] | ||
"use strict"; | ||
var obj = {}; | ||
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { | ||
var k = keys_1[_i]; | ||
obj[k] = function () { return "12"; }; // shouldn't cause a complexity error | ||
} | ||
var obj2 = {}; | ||
for (var _a = 0, keys_2 = keys; _a < keys_2.length; _a++) { | ||
var k = keys_2[_a]; | ||
obj2[k] = function () { return "12"; }; // shouldn't cause a complexity error | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
=== tests/cases/compiler/partialOfLargeAPIIsAbleToBeWorkedWith.ts === | ||
interface MyAPI { | ||
>MyAPI : Symbol(MyAPI, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 0, 0)) | ||
|
||
0: (x: 0) => string; | ||
>0 : Symbol(MyAPI[0], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 0, 17)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 1, 8)) | ||
|
||
1: (x: 1) => string; | ||
>1 : Symbol(MyAPI[1], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 1, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 2, 8)) | ||
|
||
2: (x: 2) => string; | ||
>2 : Symbol(MyAPI[2], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 2, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 3, 8)) | ||
|
||
3: (x: 3) => string; | ||
>3 : Symbol(MyAPI[3], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 3, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 4, 8)) | ||
|
||
4: (x: 4) => string; | ||
>4 : Symbol(MyAPI[4], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 4, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 5, 8)) | ||
|
||
5: (x: 5) => string; | ||
>5 : Symbol(MyAPI[5], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 5, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 6, 8)) | ||
|
||
6: (x: 6) => string; | ||
>6 : Symbol(MyAPI[6], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 6, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 7, 8)) | ||
|
||
7: (x: 7) => string; | ||
>7 : Symbol(MyAPI[7], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 7, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 8, 8)) | ||
|
||
8: (x: 8) => string; | ||
>8 : Symbol(MyAPI[8], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 8, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 9, 8)) | ||
|
||
9: (x: 9) => string; | ||
>9 : Symbol(MyAPI[9], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 9, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 10, 8)) | ||
|
||
10: (x: 10) => string; | ||
>10 : Symbol(MyAPI[10], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 10, 24)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 11, 9)) | ||
|
||
11: (x: 11) => string; | ||
>11 : Symbol(MyAPI[11], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 11, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 12, 9)) | ||
|
||
12: (x: 12) => string; | ||
>12 : Symbol(MyAPI[12], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 12, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 13, 9)) | ||
|
||
13: (x: 13) => string; | ||
>13 : Symbol(MyAPI[13], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 13, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 14, 9)) | ||
|
||
14: (x: 14) => string; | ||
>14 : Symbol(MyAPI[14], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 14, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 15, 9)) | ||
|
||
15: (x: 15) => string; | ||
>15 : Symbol(MyAPI[15], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 15, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 16, 9)) | ||
|
||
16: (x: 16) => string; | ||
>16 : Symbol(MyAPI[16], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 16, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 17, 9)) | ||
|
||
17: (x: 17) => string; | ||
>17 : Symbol(MyAPI[17], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 17, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 18, 9)) | ||
|
||
18: (x: 18) => string; | ||
>18 : Symbol(MyAPI[18], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 18, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 19, 9)) | ||
|
||
19: (x: 19) => string; | ||
>19 : Symbol(MyAPI[19], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 19, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 20, 9)) | ||
|
||
20: (x: 20) => string; | ||
>20 : Symbol(MyAPI[20], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 20, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 21, 9)) | ||
|
||
21: (x: 21) => string; | ||
>21 : Symbol(MyAPI[21], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 21, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 22, 9)) | ||
|
||
22: (x: 22) => string; | ||
>22 : Symbol(MyAPI[22], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 22, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 23, 9)) | ||
|
||
23: (x: 23) => string; | ||
>23 : Symbol(MyAPI[23], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 23, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 24, 9)) | ||
|
||
24: (x: 24) => string; | ||
>24 : Symbol(MyAPI[24], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 24, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 25, 9)) | ||
|
||
25: (x: 25) => string; | ||
>25 : Symbol(MyAPI[25], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 25, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 26, 9)) | ||
|
||
26: (x: 26) => string; | ||
>26 : Symbol(MyAPI[26], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 26, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 27, 9)) | ||
|
||
27: (x: 27) => string; | ||
>27 : Symbol(MyAPI[27], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 27, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 28, 9)) | ||
|
||
28: (x: 28) => string; | ||
>28 : Symbol(MyAPI[28], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 28, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 29, 9)) | ||
|
||
29: (x: 29) => string; | ||
>29 : Symbol(MyAPI[29], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 29, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 30, 9)) | ||
|
||
30: (x: 30) => string; | ||
>30 : Symbol(MyAPI[30], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 30, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 31, 9)) | ||
|
||
31: (x: 31) => string; | ||
>31 : Symbol(MyAPI[31], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 31, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 32, 9)) | ||
|
||
32: (x: 32) => string; | ||
>32 : Symbol(MyAPI[32], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 32, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 33, 9)) | ||
|
||
33: (x: 33) => string; | ||
>33 : Symbol(MyAPI[33], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 33, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 34, 9)) | ||
|
||
34: (x: 34) => string; | ||
>34 : Symbol(MyAPI[34], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 34, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 35, 9)) | ||
|
||
35: (x: 35) => string; | ||
>35 : Symbol(MyAPI[35], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 35, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 36, 9)) | ||
|
||
36: (x: 36) => string; | ||
>36 : Symbol(MyAPI[36], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 36, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 37, 9)) | ||
|
||
37: (x: 37) => string; | ||
>37 : Symbol(MyAPI[37], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 37, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 38, 9)) | ||
|
||
38: (x: 38) => string; | ||
>38 : Symbol(MyAPI[38], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 38, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 39, 9)) | ||
|
||
39: (x: 39) => string; | ||
>39 : Symbol(MyAPI[39], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 39, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 40, 9)) | ||
|
||
40: (x: 40) => string; | ||
>40 : Symbol(MyAPI[40], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 40, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 41, 9)) | ||
|
||
41: (x: 41) => string; | ||
>41 : Symbol(MyAPI[41], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 41, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 42, 9)) | ||
|
||
42: (x: 42) => string; | ||
>42 : Symbol(MyAPI[42], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 42, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 43, 9)) | ||
|
||
43: (x: 43) => string; | ||
>43 : Symbol(MyAPI[43], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 43, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 44, 9)) | ||
|
||
44: (x: 44) => string; | ||
>44 : Symbol(MyAPI[44], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 44, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 45, 9)) | ||
|
||
45: (x: 45) => string; | ||
>45 : Symbol(MyAPI[45], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 45, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 46, 9)) | ||
|
||
46: (x: 46) => string; | ||
>46 : Symbol(MyAPI[46], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 46, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 47, 9)) | ||
|
||
47: (x: 47) => string; | ||
>47 : Symbol(MyAPI[47], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 47, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 48, 9)) | ||
|
||
48: (x: 48) => string; | ||
>48 : Symbol(MyAPI[48], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 48, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 49, 9)) | ||
|
||
49: (x: 49) => string; | ||
>49 : Symbol(MyAPI[49], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 49, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 50, 9)) | ||
|
||
50: (x: 50) => string; | ||
>50 : Symbol(MyAPI[50], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 50, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 51, 9)) | ||
|
||
51: (x: 51) => string; | ||
>51 : Symbol(MyAPI[51], Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 51, 26)) | ||
>x : Symbol(x, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 52, 9)) | ||
} | ||
|
||
const obj: Partial<MyAPI> = {}; | ||
>obj : Symbol(obj, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 55, 5)) | ||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --)) | ||
>MyAPI : Symbol(MyAPI, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 0, 0)) | ||
|
||
declare var keys: (keyof MyAPI)[]; | ||
>keys : Symbol(keys, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 57, 11)) | ||
>MyAPI : Symbol(MyAPI, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 0, 0)) | ||
|
||
for (const k of keys) { | ||
>k : Symbol(k, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 59, 10)) | ||
>keys : Symbol(keys, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 57, 11)) | ||
|
||
obj[k] = () => "12"; // shouldn't cause a complexity error | ||
>obj : Symbol(obj, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 55, 5)) | ||
>k : Symbol(k, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 59, 10)) | ||
} | ||
|
||
type PartialNull<T> = {[K in keyof T]?: T[K] | null}; | ||
>PartialNull : Symbol(PartialNull, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 61, 1)) | ||
>T : Symbol(T, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 63, 17)) | ||
>K : Symbol(K, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 63, 24)) | ||
>T : Symbol(T, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 63, 17)) | ||
>T : Symbol(T, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 63, 17)) | ||
>K : Symbol(K, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 63, 24)) | ||
|
||
const obj2: PartialNull<MyAPI> = {}; | ||
>obj2 : Symbol(obj2, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 65, 5)) | ||
>PartialNull : Symbol(PartialNull, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 61, 1)) | ||
>MyAPI : Symbol(MyAPI, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 0, 0)) | ||
|
||
for (const k of keys) { | ||
>k : Symbol(k, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 67, 10)) | ||
>keys : Symbol(keys, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 57, 11)) | ||
|
||
obj2[k] = () => "12"; // shouldn't cause a complexity error | ||
>obj2 : Symbol(obj2, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 65, 5)) | ||
>k : Symbol(k, Decl(partialOfLargeAPIIsAbleToBeWorkedWith.ts, 67, 10)) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you add Null and Undefined to TypeFlags.IncludesMask to avoid the second check?
actually, would it be possible to add a special TypeFlags.EveryUnion that gets calculated in
addTypesToIntersection
and then added toincludes
? This uses up another TypeFlags, but is faster than trying to return two things. So..maybe not worth it.I do notice that the two calls to extractIrreducible might iterate
typeSet
twice whenever it contains all-unions, but doesn't have anynull
orundefined
s.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, because we're looking for members-of-members that are undefined-or-null. We'd need 3 (or two) brand new flags (null and undefined are already used to track weather the intersection itself contains them). One for "every member is a union", one for "every member contains
undefined
", and one for "every member containsnull
". We only have two unused type flags left (all currently assigned type flags have a meaning in intersection construction), sooo.... Yeah.This already bails early in every common scenario, the worst case where it's not needed is soemthing like a 52 element union where the first 51 contain
undefined
, but the 52nd containsnull
, which is irreducible and, notably, will trigger the "excessively large union" check in theelse
clause once the filtering fails, and cease to do any more work. So the "worst case" is either the case where it needs to occur and all the work needs to be done, or where it's very close to that but not, and will likely be converted toany
, anyway.