Skip to content

Commit ca10b7a

Browse files
committed
Add checks for remaining truthiness positions
1 parent 14d3c69 commit ca10b7a

5 files changed

+516
-5
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20949,6 +20949,7 @@ namespace ts {
2094920949
}
2095020950
return numberType;
2095120951
case SyntaxKind.ExclamationToken:
20952+
checkTruthinessExpression(node.operand);
2095220953
const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy);
2095320954
return facts === TypeFacts.Truthy ? falseType :
2095420955
facts === TypeFacts.Falsy ? trueType :
@@ -21316,7 +21317,14 @@ namespace ts {
2131621317
if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) {
2131721318
return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode);
2131821319
}
21319-
let leftType = checkExpression(left, checkMode);
21320+
let leftType: Type;
21321+
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) {
21322+
leftType = checkTruthinessExpression(left, checkMode);
21323+
}
21324+
else {
21325+
leftType = checkExpression(left, checkMode);
21326+
}
21327+
2132021328
let rightType = checkExpression(right, checkMode);
2132121329
switch (operator) {
2132221330
case SyntaxKind.AsteriskToken:
@@ -21649,7 +21657,7 @@ namespace ts {
2164921657
}
2165021658

2165121659
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
21652-
checkExpression(node.condition);
21660+
checkTruthinessExpression(node.condition);
2165321661
const type1 = checkExpression(node.whenTrue, checkMode);
2165421662
const type2 = checkExpression(node.whenFalse, checkMode);
2165521663
return getUnionType([type1, type2], UnionReduction.Subtype);
@@ -24538,9 +24546,9 @@ namespace ts {
2453824546
checkSourceElement(node.statement);
2453924547
}
2454024548

24541-
function checkTruthinessExpression(node: Expression) {
24542-
const type = checkExpression(node);
24543-
if (type === voidType) {
24549+
function checkTruthinessExpression(node: Expression, checkMode?: CheckMode) {
24550+
const type = checkExpression(node, checkMode);
24551+
if (type.flags & TypeFlags.Void) {
2454424552
error(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness);
2454524553
}
2454624554
return type;
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(36,1): error TS1345: An expression of type 'void' cannot be tested for truthiness
2+
tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(39,1): error TS1345: An expression of type 'void' cannot be tested for truthiness
3+
tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(58,20): error TS1345: An expression of type 'void' cannot be tested for truthiness
4+
tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(61,23): error TS1345: An expression of type 'void' cannot be tested for truthiness
5+
tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(63,32): error TS1345: An expression of type 'void' cannot be tested for truthiness
6+
7+
8+
==== tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts (5 errors) ====
9+
//Cond ? Expr1 : Expr2, Cond is of object type, Expr1 and Expr2 have the same type
10+
var condObject: Object;
11+
12+
var exprAny1: any;
13+
var exprBoolean1: boolean;
14+
var exprNumber1: number;
15+
var exprString1: string;
16+
var exprIsObject1: Object;
17+
18+
var exprAny2: any;
19+
var exprBoolean2: boolean;
20+
var exprNumber2: number;
21+
var exprString2: string;
22+
var exprIsObject2: Object;
23+
24+
function foo() { };
25+
class C { static doIt: () => void };
26+
27+
//Cond is an object type variable
28+
condObject ? exprAny1 : exprAny2;
29+
condObject ? exprBoolean1 : exprBoolean2;
30+
condObject ? exprNumber1 : exprNumber2;
31+
condObject ? exprString1 : exprString2;
32+
condObject ? exprIsObject1 : exprIsObject2;
33+
condObject ? exprString1 : exprBoolean1; // union
34+
35+
//Cond is an object type literal
36+
((a: string) => a.length) ? exprAny1 : exprAny2;
37+
((a: string) => a.length) ? exprBoolean1 : exprBoolean2;
38+
({}) ? exprNumber1 : exprNumber2;
39+
({ a: 1, b: "s" }) ? exprString1 : exprString2;
40+
({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2;
41+
({ a: 1, b: "s" }) ? exprString1: exprBoolean1; // union
42+
43+
//Cond is an object type expression
44+
foo() ? exprAny1 : exprAny2;
45+
~~~~~
46+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
47+
new Date() ? exprBoolean1 : exprBoolean2;
48+
new C() ? exprNumber1 : exprNumber2;
49+
C.doIt() ? exprString1 : exprString2;
50+
~~~~~~~~
51+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
52+
condObject.valueOf() ? exprIsObject1 : exprIsObject2;
53+
new Date() ? exprString1 : exprBoolean1; // union
54+
55+
//Results shoud be same as Expr1 and Expr2
56+
var resultIsAny1 = condObject ? exprAny1 : exprAny2;
57+
var resultIsBoolean1 = condObject ? exprBoolean1 : exprBoolean2;
58+
var resultIsNumber1 = condObject ? exprNumber1 : exprNumber2;
59+
var resultIsString1 = condObject ? exprString1 : exprString2;
60+
var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2;
61+
var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union
62+
63+
var resultIsAny2 = ((a: string) => a.length) ? exprAny1 : exprAny2;
64+
var resultIsBoolean2 = ((a: string) => a.length) ? exprBoolean1 : exprBoolean2;
65+
var resultIsNumber2 = ({}) ? exprNumber1 : exprNumber2;
66+
var resultIsString2 = ({ a: 1, b: "s" }) ? exprString1 : exprString2;
67+
var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2;
68+
var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union
69+
70+
var resultIsAny3 = foo() ? exprAny1 : exprAny2;
71+
~~~~~
72+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
73+
var resultIsBoolean3 = new Date() ? exprBoolean1 : exprBoolean2;
74+
var resultIsNumber3 = new C() ? exprNumber1 : exprNumber2;
75+
var resultIsString3 = C.doIt() ? exprString1 : exprString2;
76+
~~~~~~~~
77+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
78+
var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2;
79+
var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union
80+
~~~~~~~~
81+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
82+
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(46,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
2+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(47,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
3+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(48,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
4+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(49,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
5+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(50,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
6+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(51,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
7+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(52,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
8+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(53,12): error TS1345: An expression of type 'void' cannot be tested for truthiness
9+
10+
11+
==== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts (8 errors) ====
12+
const a = [0];
13+
const s = "";
14+
const x = 0;
15+
const b = false;
16+
const v: void = undefined;
17+
const u = undefined;
18+
const n = null;
19+
const z = s || x || u;
20+
21+
const a1 = a && a;
22+
const a2 = a && s;
23+
const a3 = a && x;
24+
const a4 = a && b;
25+
const a5 = a && v;
26+
const a6 = a && u;
27+
const a7 = a && n;
28+
const a8 = a && z;
29+
30+
const s1 = s && a;
31+
const s2 = s && s;
32+
const s3 = s && x;
33+
const s4 = s && b;
34+
const s5 = s && v;
35+
const s6 = s && u;
36+
const s7 = s && n;
37+
const s8 = s && z;
38+
39+
const x1 = x && a;
40+
const x2 = x && s;
41+
const x3 = x && x;
42+
const x4 = x && b;
43+
const x5 = x && v;
44+
const x6 = x && u;
45+
const x7 = x && n;
46+
const x8 = x && z;
47+
48+
const b1 = b && a;
49+
const b2 = b && s;
50+
const b3 = b && x;
51+
const b4 = b && b;
52+
const b5 = b && v;
53+
const b6 = b && u;
54+
const b7 = b && n;
55+
const b8 = b && z;
56+
57+
const v1 = v && a;
58+
~
59+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
60+
const v2 = v && s;
61+
~
62+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
63+
const v3 = v && x;
64+
~
65+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
66+
const v4 = v && b;
67+
~
68+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
69+
const v5 = v && v;
70+
~
71+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
72+
const v6 = v && u;
73+
~
74+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
75+
const v7 = v && n;
76+
~
77+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
78+
const v8 = v && z;
79+
~
80+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
81+
82+
const u1 = u && a;
83+
const u2 = u && s;
84+
const u3 = u && x;
85+
const u4 = u && b;
86+
const u5 = u && v;
87+
const u6 = u && u;
88+
const u7 = u && n;
89+
const u8 = u && z;
90+
91+
const n1 = n && a;
92+
const n2 = n && s;
93+
const n3 = n && x;
94+
const n4 = n && b;
95+
const n5 = n && v;
96+
const n6 = n && u;
97+
const n7 = n && n;
98+
const n8 = n && z;
99+
100+
const z1 = z && a;
101+
const z2 = z && s;
102+
const z3 = z && x;
103+
const z4 = z && b;
104+
const z5 = z && v;
105+
const z6 = z && u;
106+
const z7 = z && n;
107+
const z8 = z && z;
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(19,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
2+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(30,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
3+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(41,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
4+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(52,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
5+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(63,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
6+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(74,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
7+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(85,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
8+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(96,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
9+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(107,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
10+
tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(118,11): error TS1345: An expression of type 'void' cannot be tested for truthiness
11+
12+
13+
==== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts (10 errors) ====
14+
// The && operator permits the operands to be of any type and produces a result of the same
15+
// type as the second operand.
16+
17+
enum E { a, b, c }
18+
19+
var a1: any;
20+
var a2: boolean;
21+
var a3: number
22+
var a4: string;
23+
var a5: void;
24+
var a6: E;
25+
var a7: {};
26+
var a8: string[];
27+
28+
var ra1 = a1 && a1;
29+
var ra2 = a2 && a1;
30+
var ra3 = a3 && a1;
31+
var ra4 = a4 && a1;
32+
var ra5 = a5 && a1;
33+
~~
34+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
35+
var ra6 = a6 && a1;
36+
var ra7 = a7 && a1;
37+
var ra8 = a8 && a1;
38+
var ra9 = null && a1;
39+
var ra10 = undefined && a1;
40+
41+
var rb1 = a1 && a2;
42+
var rb2 = a2 && a2;
43+
var rb3 = a3 && a2;
44+
var rb4 = a4 && a2;
45+
var rb5 = a5 && a2;
46+
~~
47+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
48+
var rb6 = a6 && a2;
49+
var rb7 = a7 && a2;
50+
var rb8 = a8 && a2;
51+
var rb9 = null && a2;
52+
var rb10 = undefined && a2;
53+
54+
var rc1 = a1 && a3;
55+
var rc2 = a2 && a3;
56+
var rc3 = a3 && a3;
57+
var rc4 = a4 && a3;
58+
var rc5 = a5 && a3;
59+
~~
60+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
61+
var rc6 = a6 && a3;
62+
var rc7 = a7 && a3;
63+
var rc8 = a8 && a3;
64+
var rc9 = null && a3;
65+
var rc10 = undefined && a3;
66+
67+
var rd1 = a1 && a4;
68+
var rd2 = a2 && a4;
69+
var rd3 = a3 && a4;
70+
var rd4 = a4 && a4;
71+
var rd5 = a5 && a4;
72+
~~
73+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
74+
var rd6 = a6 && a4;
75+
var rd7 = a7 && a4;
76+
var rd8 = a8 && a4;
77+
var rd9 = null && a4;
78+
var rd10 = undefined && a4;
79+
80+
var re1 = a1 && a5;
81+
var re2 = a2 && a5;
82+
var re3 = a3 && a5;
83+
var re4 = a4 && a5;
84+
var re5 = a5 && a5;
85+
~~
86+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
87+
var re6 = a6 && a5;
88+
var re7 = a7 && a5;
89+
var re8 = a8 && a5;
90+
var re9 = null && a5;
91+
var re10 = undefined && a5;
92+
93+
var rf1 = a1 && a6;
94+
var rf2 = a2 && a6;
95+
var rf3 = a3 && a6;
96+
var rf4 = a4 && a6;
97+
var rf5 = a5 && a6;
98+
~~
99+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
100+
var rf6 = a6 && a6;
101+
var rf7 = a7 && a6;
102+
var rf8 = a8 && a6;
103+
var rf9 = null && a6;
104+
var rf10 = undefined && a6;
105+
106+
var rg1 = a1 && a7;
107+
var rg2 = a2 && a7;
108+
var rg3 = a3 && a7;
109+
var rg4 = a4 && a7;
110+
var rg5 = a5 && a7;
111+
~~
112+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
113+
var rg6 = a6 && a7;
114+
var rg7 = a7 && a7;
115+
var rg8 = a8 && a7;
116+
var rg9 = null && a7;
117+
var rg10 = undefined && a7;
118+
119+
var rh1 = a1 && a8;
120+
var rh2 = a2 && a8;
121+
var rh3 = a3 && a8;
122+
var rh4 = a4 && a8;
123+
var rh5 = a5 && a8;
124+
~~
125+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
126+
var rh6 = a6 && a8;
127+
var rh7 = a7 && a8;
128+
var rh8 = a8 && a8;
129+
var rh9 = null && a8;
130+
var rh10 = undefined && a8;
131+
132+
var ri1 = a1 && null;
133+
var ri2 = a2 && null;
134+
var ri3 = a3 && null;
135+
var ri4 = a4 && null;
136+
var ri5 = a5 && null;
137+
~~
138+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
139+
var ri6 = a6 && null;
140+
var ri7 = a7 && null;
141+
var ri8 = a8 && null;
142+
var ri9 = null && null;
143+
var ri10 = undefined && null;
144+
145+
var rj1 = a1 && undefined;
146+
var rj2 = a2 && undefined;
147+
var rj3 = a3 && undefined;
148+
var rj4 = a4 && undefined;
149+
var rj5 = a5 && undefined;
150+
~~
151+
!!! error TS1345: An expression of type 'void' cannot be tested for truthiness
152+
var rj6 = a6 && undefined;
153+
var rj7 = a7 && undefined;
154+
var rj8 = a8 && undefined;
155+
var rj9 = null && undefined;
156+
var rj10 = undefined && undefined;

0 commit comments

Comments
 (0)