Skip to content

Commit b144b5b

Browse files
committed
Merge pull request #5660 from weswigham/undefined-type-guards
Ignore typeof x === "undefined" type guards when narrowing
2 parents bd39847 + d7ddcc4 commit b144b5b

File tree

5 files changed

+1313
-0
lines changed

5 files changed

+1313
-0
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ namespace ts {
200200
"symbol": {
201201
type: esSymbolType,
202202
flags: TypeFlags.ESSymbol
203+
},
204+
"undefined": {
205+
type: undefinedType,
206+
flags: TypeFlags.ContainsUndefinedOrNull
203207
}
204208
};
205209

@@ -6475,6 +6479,10 @@ namespace ts {
64756479
assumeTrue = !assumeTrue;
64766480
}
64776481
const typeInfo = primitiveTypeInfo[right.text];
6482+
// Don't narrow `undefined`
6483+
if (typeInfo && typeInfo.type === undefinedType) {
6484+
return type;
6485+
}
64786486
// If the type to be narrowed is any and we're checking a primitive with assumeTrue=true, return the primitive
64796487
if (!!(type.flags & TypeFlags.Any) && typeInfo && assumeTrue) {
64806488
return typeInfo.type;
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
//// [typeGuardTypeOfUndefined.ts]
2+
// undefined type guard adds no new type information
3+
function test1(a: any) {
4+
if (typeof a !== "undefined") {
5+
if (typeof a === "boolean") {
6+
a;
7+
}
8+
else {
9+
a;
10+
}
11+
}
12+
else {
13+
a;
14+
}
15+
}
16+
17+
function test2(a: any) {
18+
if (typeof a === "undefined") {
19+
if (typeof a === "boolean") {
20+
a;
21+
}
22+
else {
23+
a;
24+
}
25+
}
26+
else {
27+
a;
28+
}
29+
}
30+
31+
function test3(a: any) {
32+
if (typeof a === "undefined" || typeof a === "boolean") {
33+
a;
34+
}
35+
else {
36+
a;
37+
}
38+
}
39+
40+
function test4(a: any) {
41+
if (typeof a !== "undefined" && typeof a === "boolean") {
42+
a;
43+
}
44+
else {
45+
a;
46+
}
47+
}
48+
49+
function test5(a: boolean | void) {
50+
if (typeof a !== "undefined") {
51+
if (typeof a === "boolean") {
52+
a;
53+
}
54+
else {
55+
a;
56+
}
57+
}
58+
else {
59+
a;
60+
}
61+
}
62+
63+
function test6(a: boolean | void) {
64+
if (typeof a === "undefined") {
65+
if (typeof a === "boolean") {
66+
a;
67+
}
68+
else {
69+
a;
70+
}
71+
}
72+
else {
73+
a;
74+
}
75+
}
76+
77+
function test7(a: boolean | void) {
78+
if (typeof a === "undefined" || typeof a === "boolean") {
79+
a;
80+
}
81+
else {
82+
a;
83+
}
84+
}
85+
86+
function test8(a: boolean | void) {
87+
if (typeof a !== "undefined" && typeof a === "boolean") {
88+
a;
89+
}
90+
else {
91+
a;
92+
}
93+
}
94+
95+
function test9(a: boolean | number) {
96+
if (typeof a !== "undefined") {
97+
if (typeof a === "boolean") {
98+
a;
99+
}
100+
else {
101+
a;
102+
}
103+
}
104+
else {
105+
a;
106+
}
107+
}
108+
109+
function test10(a: boolean | number) {
110+
if (typeof a === "undefined") {
111+
if (typeof a === "boolean") {
112+
a;
113+
}
114+
else {
115+
a;
116+
}
117+
}
118+
else {
119+
a;
120+
}
121+
}
122+
123+
function test11(a: boolean | number) {
124+
if (typeof a === "undefined" || typeof a === "boolean") {
125+
a;
126+
}
127+
else {
128+
a;
129+
}
130+
}
131+
132+
function test12(a: boolean | number) {
133+
if (typeof a !== "undefined" && typeof a === "boolean") {
134+
a;
135+
}
136+
else {
137+
a;
138+
}
139+
}
140+
141+
function test13(a: boolean | number | void) {
142+
if (typeof a !== "undefined") {
143+
if (typeof a === "boolean") {
144+
a;
145+
}
146+
else {
147+
a;
148+
}
149+
}
150+
else {
151+
a;
152+
}
153+
}
154+
155+
function test14(a: boolean | number | void) {
156+
if (typeof a === "undefined") {
157+
if (typeof a === "boolean") {
158+
a;
159+
}
160+
else {
161+
a;
162+
}
163+
}
164+
else {
165+
a;
166+
}
167+
}
168+
169+
function test15(a: boolean | number | void) {
170+
if (typeof a === "undefined" || typeof a === "boolean") {
171+
a;
172+
}
173+
else {
174+
a;
175+
}
176+
}
177+
178+
function test16(a: boolean | number | void) {
179+
if (typeof a !== "undefined" && typeof a === "boolean") {
180+
a;
181+
}
182+
else {
183+
a;
184+
}
185+
}
186+
187+
188+
//// [typeGuardTypeOfUndefined.js]
189+
// undefined type guard adds no new type information
190+
function test1(a) {
191+
if (typeof a !== "undefined") {
192+
if (typeof a === "boolean") {
193+
a;
194+
}
195+
else {
196+
a;
197+
}
198+
}
199+
else {
200+
a;
201+
}
202+
}
203+
function test2(a) {
204+
if (typeof a === "undefined") {
205+
if (typeof a === "boolean") {
206+
a;
207+
}
208+
else {
209+
a;
210+
}
211+
}
212+
else {
213+
a;
214+
}
215+
}
216+
function test3(a) {
217+
if (typeof a === "undefined" || typeof a === "boolean") {
218+
a;
219+
}
220+
else {
221+
a;
222+
}
223+
}
224+
function test4(a) {
225+
if (typeof a !== "undefined" && typeof a === "boolean") {
226+
a;
227+
}
228+
else {
229+
a;
230+
}
231+
}
232+
function test5(a) {
233+
if (typeof a !== "undefined") {
234+
if (typeof a === "boolean") {
235+
a;
236+
}
237+
else {
238+
a;
239+
}
240+
}
241+
else {
242+
a;
243+
}
244+
}
245+
function test6(a) {
246+
if (typeof a === "undefined") {
247+
if (typeof a === "boolean") {
248+
a;
249+
}
250+
else {
251+
a;
252+
}
253+
}
254+
else {
255+
a;
256+
}
257+
}
258+
function test7(a) {
259+
if (typeof a === "undefined" || typeof a === "boolean") {
260+
a;
261+
}
262+
else {
263+
a;
264+
}
265+
}
266+
function test8(a) {
267+
if (typeof a !== "undefined" && typeof a === "boolean") {
268+
a;
269+
}
270+
else {
271+
a;
272+
}
273+
}
274+
function test9(a) {
275+
if (typeof a !== "undefined") {
276+
if (typeof a === "boolean") {
277+
a;
278+
}
279+
else {
280+
a;
281+
}
282+
}
283+
else {
284+
a;
285+
}
286+
}
287+
function test10(a) {
288+
if (typeof a === "undefined") {
289+
if (typeof a === "boolean") {
290+
a;
291+
}
292+
else {
293+
a;
294+
}
295+
}
296+
else {
297+
a;
298+
}
299+
}
300+
function test11(a) {
301+
if (typeof a === "undefined" || typeof a === "boolean") {
302+
a;
303+
}
304+
else {
305+
a;
306+
}
307+
}
308+
function test12(a) {
309+
if (typeof a !== "undefined" && typeof a === "boolean") {
310+
a;
311+
}
312+
else {
313+
a;
314+
}
315+
}
316+
function test13(a) {
317+
if (typeof a !== "undefined") {
318+
if (typeof a === "boolean") {
319+
a;
320+
}
321+
else {
322+
a;
323+
}
324+
}
325+
else {
326+
a;
327+
}
328+
}
329+
function test14(a) {
330+
if (typeof a === "undefined") {
331+
if (typeof a === "boolean") {
332+
a;
333+
}
334+
else {
335+
a;
336+
}
337+
}
338+
else {
339+
a;
340+
}
341+
}
342+
function test15(a) {
343+
if (typeof a === "undefined" || typeof a === "boolean") {
344+
a;
345+
}
346+
else {
347+
a;
348+
}
349+
}
350+
function test16(a) {
351+
if (typeof a !== "undefined" && typeof a === "boolean") {
352+
a;
353+
}
354+
else {
355+
a;
356+
}
357+
}

0 commit comments

Comments
 (0)