Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 83bc70d

Browse filesBrowse files
authored
Merge pull request microsoft#23782 from Microsoft/controlFlowNullTypeAndLiteral
Control flow for null type vs. literal
2 parents 33ba250 + a286cff commit 83bc70d
Copy full SHA for 83bc70d

6 files changed

+287-1Lines changed: 287 additions & 1 deletion

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13690,7 +13690,7 @@ namespace ts {
1369013690
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
1369113691
const facts = doubleEquals ?
1369213692
assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
13693-
value.kind === SyntaxKind.NullKeyword ?
13693+
valueType.flags & TypeFlags.Null ?
1369413694
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
1369513695
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
1369613696
return getTypeWithFacts(type, facts);
Collapse file
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
tests/cases/compiler/controlFlowNullTypeAndLiteral.ts(15,12): error TS2345: Argument of type 'null' is not assignable to parameter of type 'number'.
2+
tests/cases/compiler/controlFlowNullTypeAndLiteral.ts(17,12): error TS2345: Argument of type 'null' is not assignable to parameter of type 'number'.
3+
tests/cases/compiler/controlFlowNullTypeAndLiteral.ts(21,15): error TS2322: Type 'null' is not assignable to type 'string'.
4+
5+
6+
==== tests/cases/compiler/controlFlowNullTypeAndLiteral.ts (3 errors) ====
7+
// Repros from #23771
8+
9+
const myNull: null = null;
10+
const objWithValMaybeNull: { val: number | null } = { val: 1 };
11+
const addOne = function (num: number) {
12+
return num + 1;
13+
}
14+
15+
if (objWithValMaybeNull.val !== null)
16+
addOne(objWithValMaybeNull.val);
17+
if (objWithValMaybeNull.val !== myNull)
18+
addOne(objWithValMaybeNull.val);
19+
20+
if (objWithValMaybeNull.val === null)
21+
addOne(objWithValMaybeNull.val); // Error
22+
~~~~~~~~~~~~~~~~~~~~~~~
23+
!!! error TS2345: Argument of type 'null' is not assignable to parameter of type 'number'.
24+
if (objWithValMaybeNull.val === myNull)
25+
addOne(objWithValMaybeNull.val); // Error
26+
~~~~~~~~~~~~~~~~~~~~~~~
27+
!!! error TS2345: Argument of type 'null' is not assignable to parameter of type 'number'.
28+
29+
function f(x: number | null) {
30+
if(x === myNull) {
31+
const s: string = x; // Error
32+
~
33+
!!! error TS2322: Type 'null' is not assignable to type 'string'.
34+
}
35+
}
36+
Collapse file
+47Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//// [controlFlowNullTypeAndLiteral.ts]
2+
// Repros from #23771
3+
4+
const myNull: null = null;
5+
const objWithValMaybeNull: { val: number | null } = { val: 1 };
6+
const addOne = function (num: number) {
7+
return num + 1;
8+
}
9+
10+
if (objWithValMaybeNull.val !== null)
11+
addOne(objWithValMaybeNull.val);
12+
if (objWithValMaybeNull.val !== myNull)
13+
addOne(objWithValMaybeNull.val);
14+
15+
if (objWithValMaybeNull.val === null)
16+
addOne(objWithValMaybeNull.val); // Error
17+
if (objWithValMaybeNull.val === myNull)
18+
addOne(objWithValMaybeNull.val); // Error
19+
20+
function f(x: number | null) {
21+
if(x === myNull) {
22+
const s: string = x; // Error
23+
}
24+
}
25+
26+
27+
//// [controlFlowNullTypeAndLiteral.js]
28+
"use strict";
29+
// Repros from #23771
30+
var myNull = null;
31+
var objWithValMaybeNull = { val: 1 };
32+
var addOne = function (num) {
33+
return num + 1;
34+
};
35+
if (objWithValMaybeNull.val !== null)
36+
addOne(objWithValMaybeNull.val);
37+
if (objWithValMaybeNull.val !== myNull)
38+
addOne(objWithValMaybeNull.val);
39+
if (objWithValMaybeNull.val === null)
40+
addOne(objWithValMaybeNull.val); // Error
41+
if (objWithValMaybeNull.val === myNull)
42+
addOne(objWithValMaybeNull.val); // Error
43+
function f(x) {
44+
if (x === myNull) {
45+
var s = x; // Error
46+
}
47+
}
Collapse file
+79Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
=== tests/cases/compiler/controlFlowNullTypeAndLiteral.ts ===
2+
// Repros from #23771
3+
4+
const myNull: null = null;
5+
>myNull : Symbol(myNull, Decl(controlFlowNullTypeAndLiteral.ts, 2, 5))
6+
7+
const objWithValMaybeNull: { val: number | null } = { val: 1 };
8+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
9+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
10+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 53))
11+
12+
const addOne = function (num: number) {
13+
>addOne : Symbol(addOne, Decl(controlFlowNullTypeAndLiteral.ts, 4, 5))
14+
>num : Symbol(num, Decl(controlFlowNullTypeAndLiteral.ts, 4, 25))
15+
16+
return num + 1;
17+
>num : Symbol(num, Decl(controlFlowNullTypeAndLiteral.ts, 4, 25))
18+
}
19+
20+
if (objWithValMaybeNull.val !== null)
21+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
22+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
23+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
24+
25+
addOne(objWithValMaybeNull.val);
26+
>addOne : Symbol(addOne, Decl(controlFlowNullTypeAndLiteral.ts, 4, 5))
27+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
28+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
29+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
30+
31+
if (objWithValMaybeNull.val !== myNull)
32+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
33+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
34+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
35+
>myNull : Symbol(myNull, Decl(controlFlowNullTypeAndLiteral.ts, 2, 5))
36+
37+
addOne(objWithValMaybeNull.val);
38+
>addOne : Symbol(addOne, Decl(controlFlowNullTypeAndLiteral.ts, 4, 5))
39+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
40+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
41+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
42+
43+
if (objWithValMaybeNull.val === null)
44+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
45+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
46+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
47+
48+
addOne(objWithValMaybeNull.val); // Error
49+
>addOne : Symbol(addOne, Decl(controlFlowNullTypeAndLiteral.ts, 4, 5))
50+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
51+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
52+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
53+
54+
if (objWithValMaybeNull.val === myNull)
55+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
56+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
57+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
58+
>myNull : Symbol(myNull, Decl(controlFlowNullTypeAndLiteral.ts, 2, 5))
59+
60+
addOne(objWithValMaybeNull.val); // Error
61+
>addOne : Symbol(addOne, Decl(controlFlowNullTypeAndLiteral.ts, 4, 5))
62+
>objWithValMaybeNull.val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
63+
>objWithValMaybeNull : Symbol(objWithValMaybeNull, Decl(controlFlowNullTypeAndLiteral.ts, 3, 5))
64+
>val : Symbol(val, Decl(controlFlowNullTypeAndLiteral.ts, 3, 28))
65+
66+
function f(x: number | null) {
67+
>f : Symbol(f, Decl(controlFlowNullTypeAndLiteral.ts, 16, 36))
68+
>x : Symbol(x, Decl(controlFlowNullTypeAndLiteral.ts, 18, 11))
69+
70+
if(x === myNull) {
71+
>x : Symbol(x, Decl(controlFlowNullTypeAndLiteral.ts, 18, 11))
72+
>myNull : Symbol(myNull, Decl(controlFlowNullTypeAndLiteral.ts, 2, 5))
73+
74+
const s: string = x; // Error
75+
>s : Symbol(s, Decl(controlFlowNullTypeAndLiteral.ts, 20, 13))
76+
>x : Symbol(x, Decl(controlFlowNullTypeAndLiteral.ts, 18, 11))
77+
}
78+
}
79+
Collapse file
+99Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
=== tests/cases/compiler/controlFlowNullTypeAndLiteral.ts ===
2+
// Repros from #23771
3+
4+
const myNull: null = null;
5+
>myNull : null
6+
>null : null
7+
>null : null
8+
9+
const objWithValMaybeNull: { val: number | null } = { val: 1 };
10+
>objWithValMaybeNull : { val: number | null; }
11+
>val : number | null
12+
>null : null
13+
>{ val: 1 } : { val: number; }
14+
>val : number
15+
>1 : 1
16+
17+
const addOne = function (num: number) {
18+
>addOne : (num: number) => number
19+
>function (num: number) { return num + 1;} : (num: number) => number
20+
>num : number
21+
22+
return num + 1;
23+
>num + 1 : number
24+
>num : number
25+
>1 : 1
26+
}
27+
28+
if (objWithValMaybeNull.val !== null)
29+
>objWithValMaybeNull.val !== null : boolean
30+
>objWithValMaybeNull.val : number | null
31+
>objWithValMaybeNull : { val: number | null; }
32+
>val : number | null
33+
>null : null
34+
35+
addOne(objWithValMaybeNull.val);
36+
>addOne(objWithValMaybeNull.val) : number
37+
>addOne : (num: number) => number
38+
>objWithValMaybeNull.val : number
39+
>objWithValMaybeNull : { val: number | null; }
40+
>val : number
41+
42+
if (objWithValMaybeNull.val !== myNull)
43+
>objWithValMaybeNull.val !== myNull : boolean
44+
>objWithValMaybeNull.val : number | null
45+
>objWithValMaybeNull : { val: number | null; }
46+
>val : number | null
47+
>myNull : null
48+
49+
addOne(objWithValMaybeNull.val);
50+
>addOne(objWithValMaybeNull.val) : number
51+
>addOne : (num: number) => number
52+
>objWithValMaybeNull.val : number
53+
>objWithValMaybeNull : { val: number | null; }
54+
>val : number
55+
56+
if (objWithValMaybeNull.val === null)
57+
>objWithValMaybeNull.val === null : boolean
58+
>objWithValMaybeNull.val : number | null
59+
>objWithValMaybeNull : { val: number | null; }
60+
>val : number | null
61+
>null : null
62+
63+
addOne(objWithValMaybeNull.val); // Error
64+
>addOne(objWithValMaybeNull.val) : number
65+
>addOne : (num: number) => number
66+
>objWithValMaybeNull.val : null
67+
>objWithValMaybeNull : { val: number | null; }
68+
>val : null
69+
70+
if (objWithValMaybeNull.val === myNull)
71+
>objWithValMaybeNull.val === myNull : boolean
72+
>objWithValMaybeNull.val : number | null
73+
>objWithValMaybeNull : { val: number | null; }
74+
>val : number | null
75+
>myNull : null
76+
77+
addOne(objWithValMaybeNull.val); // Error
78+
>addOne(objWithValMaybeNull.val) : number
79+
>addOne : (num: number) => number
80+
>objWithValMaybeNull.val : null
81+
>objWithValMaybeNull : { val: number | null; }
82+
>val : null
83+
84+
function f(x: number | null) {
85+
>f : (x: number | null) => void
86+
>x : number | null
87+
>null : null
88+
89+
if(x === myNull) {
90+
>x === myNull : boolean
91+
>x : number | null
92+
>myNull : null
93+
94+
const s: string = x; // Error
95+
>s : string
96+
>x : null
97+
}
98+
}
99+
Collapse file
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// @strict: true
2+
3+
// Repros from #23771
4+
5+
const myNull: null = null;
6+
const objWithValMaybeNull: { val: number | null } = { val: 1 };
7+
const addOne = function (num: number) {
8+
return num + 1;
9+
}
10+
11+
if (objWithValMaybeNull.val !== null)
12+
addOne(objWithValMaybeNull.val);
13+
if (objWithValMaybeNull.val !== myNull)
14+
addOne(objWithValMaybeNull.val);
15+
16+
if (objWithValMaybeNull.val === null)
17+
addOne(objWithValMaybeNull.val); // Error
18+
if (objWithValMaybeNull.val === myNull)
19+
addOne(objWithValMaybeNull.val); // Error
20+
21+
function f(x: number | null) {
22+
if(x === myNull) {
23+
const s: string = x; // Error
24+
}
25+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.