From 14d3c69c722793c7a007d53081977410fb521aca Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 6 Aug 2018 09:40:22 -0700 Subject: [PATCH 1/2] Disallow exprs of type `void` to be used in truthiness checks --- src/compiler/checker.ts | 16 ++++++++--- src/compiler/diagnosticMessages.json | 4 +++ src/server/scriptInfo.ts | 3 +++ .../reference/api/tsserverlibrary.d.ts | 2 +- .../reference/typePredicateInLoop.errors.txt | 27 +++++++++++++++++++ 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/typePredicateInLoop.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1391275b28f3..5353d587db970 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24512,7 +24512,7 @@ namespace ts { // Grammar checking checkGrammarStatementInAmbientContext(node); - checkExpression(node.expression); + checkTruthinessExpression(node.expression); checkSourceElement(node.thenStatement); if (node.thenStatement.kind === SyntaxKind.EmptyStatement) { @@ -24527,17 +24527,25 @@ namespace ts { checkGrammarStatementInAmbientContext(node); checkSourceElement(node.statement); - checkExpression(node.expression); + checkTruthinessExpression(node.expression); } function checkWhileStatement(node: WhileStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); - checkExpression(node.expression); + checkTruthinessExpression(node.expression); checkSourceElement(node.statement); } + function checkTruthinessExpression(node: Expression) { + const type = checkExpression(node); + if (type === voidType) { + error(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness); + } + return type; + } + function checkForStatement(node: ForStatement) { // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { @@ -24555,7 +24563,7 @@ namespace ts { } } - if (node.condition) checkExpression(node.condition); + if (node.condition) checkTruthinessExpression(node.condition); if (node.incrementor) checkExpression(node.incrementor); checkSourceElement(node.statement); if (node.locals) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index babb48797b56b..a962ba258049e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -987,6 +987,10 @@ "category": "Error", "code": 1344 }, + "An expression of type 'void' cannot be tested for truthiness": { + "category": "Error", + "code": 1345 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index cf85933e2eeff..202b4c02c1ba3 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -459,12 +459,15 @@ namespace ts.server { if (this.isDynamicOrHasMixedContent()) { this.textStorage.reload(""); this.markContainingProjectsAsDirty(); + return true; } else { if (this.textStorage.reloadWithFileText(tempFileName)) { this.markContainingProjectsAsDirty(); + return true; } } + return false; } /*@internal*/ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 188ae835b5b27..339e2394ce440 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -8114,7 +8114,7 @@ declare namespace ts.server { setOptions(formatSettings: FormatCodeSettings, preferences: UserPreferences | undefined): void; getLatestVersion(): string; saveTo(fileName: string): void; - reloadFromFile(tempFileName?: NormalizedPath): void; + reloadFromFile(tempFileName?: NormalizedPath): boolean; editContent(start: number, end: number, newText: string): void; markContainingProjectsAsDirty(): void; isOrphan(): boolean; diff --git a/tests/baselines/reference/typePredicateInLoop.errors.txt b/tests/baselines/reference/typePredicateInLoop.errors.txt new file mode 100644 index 0000000000000..d14927c22a281 --- /dev/null +++ b/tests/baselines/reference/typePredicateInLoop.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/typePredicateInLoop.ts(17,11): error TS1345: An expression of type 'void' cannot be tested for truthiness + + +==== tests/cases/compiler/typePredicateInLoop.ts (1 errors) ==== + // Repro from #12101 + + interface Type { + type: number; + } + + interface TypeExt extends Type { + arr: Type[]; + } + + const guard = (arg: Type): arg is TypeExt => arg.type === 1; + const otherFunc = (arg1: Type, arg2: TypeExt): void => {}; + + export function y(arg: Type): void { + if (guard(arg)) { + for (const ITEM of arg.arr) { + if (otherFunc(ITEM, arg)) { + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + } + } + } + } \ No newline at end of file From ca10b7a6faee03f27434a7ebffd1395744e32db6 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 6 Aug 2018 16:11:43 -0700 Subject: [PATCH 2/2] Add checks for remaining truthiness positions --- src/compiler/checker.ts | 18 +- ...alOperatorConditionIsObjectType.errors.txt | 82 +++++++++ .../logicalAndOperatorStrictMode.errors.txt | 107 ++++++++++++ ...logicalAndOperatorWithEveryType.errors.txt | 156 +++++++++++++++++ .../logicalOrOperatorWithEveryType.errors.txt | 158 ++++++++++++++++++ 5 files changed, 516 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/conditionalOperatorConditionIsObjectType.errors.txt create mode 100644 tests/baselines/reference/logicalAndOperatorStrictMode.errors.txt create mode 100644 tests/baselines/reference/logicalAndOperatorWithEveryType.errors.txt create mode 100644 tests/baselines/reference/logicalOrOperatorWithEveryType.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5353d587db970..00c4da342c469 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20949,6 +20949,7 @@ namespace ts { } return numberType; case SyntaxKind.ExclamationToken: + checkTruthinessExpression(node.operand); const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy); return facts === TypeFacts.Truthy ? falseType : facts === TypeFacts.Falsy ? trueType : @@ -21316,7 +21317,14 @@ namespace ts { if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode); } - let leftType = checkExpression(left, checkMode); + let leftType: Type; + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) { + leftType = checkTruthinessExpression(left, checkMode); + } + else { + leftType = checkExpression(left, checkMode); + } + let rightType = checkExpression(right, checkMode); switch (operator) { case SyntaxKind.AsteriskToken: @@ -21649,7 +21657,7 @@ namespace ts { } function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type { - checkExpression(node.condition); + checkTruthinessExpression(node.condition); const type1 = checkExpression(node.whenTrue, checkMode); const type2 = checkExpression(node.whenFalse, checkMode); return getUnionType([type1, type2], UnionReduction.Subtype); @@ -24538,9 +24546,9 @@ namespace ts { checkSourceElement(node.statement); } - function checkTruthinessExpression(node: Expression) { - const type = checkExpression(node); - if (type === voidType) { + function checkTruthinessExpression(node: Expression, checkMode?: CheckMode) { + const type = checkExpression(node, checkMode); + if (type.flags & TypeFlags.Void) { error(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness); } return type; diff --git a/tests/baselines/reference/conditionalOperatorConditionIsObjectType.errors.txt b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.errors.txt new file mode 100644 index 0000000000000..00adf0fe06e8c --- /dev/null +++ b/tests/baselines/reference/conditionalOperatorConditionIsObjectType.errors.txt @@ -0,0 +1,82 @@ +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(36,1): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(39,1): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(58,20): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(61,23): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts(63,32): error TS1345: An expression of type 'void' cannot be tested for truthiness + + +==== tests/cases/conformance/expressions/conditonalOperator/conditionalOperatorConditionIsObjectType.ts (5 errors) ==== + //Cond ? Expr1 : Expr2, Cond is of object type, Expr1 and Expr2 have the same type + var condObject: Object; + + var exprAny1: any; + var exprBoolean1: boolean; + var exprNumber1: number; + var exprString1: string; + var exprIsObject1: Object; + + var exprAny2: any; + var exprBoolean2: boolean; + var exprNumber2: number; + var exprString2: string; + var exprIsObject2: Object; + + function foo() { }; + class C { static doIt: () => void }; + + //Cond is an object type variable + condObject ? exprAny1 : exprAny2; + condObject ? exprBoolean1 : exprBoolean2; + condObject ? exprNumber1 : exprNumber2; + condObject ? exprString1 : exprString2; + condObject ? exprIsObject1 : exprIsObject2; + condObject ? exprString1 : exprBoolean1; // union + + //Cond is an object type literal + ((a: string) => a.length) ? exprAny1 : exprAny2; + ((a: string) => a.length) ? exprBoolean1 : exprBoolean2; + ({}) ? exprNumber1 : exprNumber2; + ({ a: 1, b: "s" }) ? exprString1 : exprString2; + ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; + ({ a: 1, b: "s" }) ? exprString1: exprBoolean1; // union + + //Cond is an object type expression + foo() ? exprAny1 : exprAny2; + ~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + new Date() ? exprBoolean1 : exprBoolean2; + new C() ? exprNumber1 : exprNumber2; + C.doIt() ? exprString1 : exprString2; + ~~~~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + condObject.valueOf() ? exprIsObject1 : exprIsObject2; + new Date() ? exprString1 : exprBoolean1; // union + + //Results shoud be same as Expr1 and Expr2 + var resultIsAny1 = condObject ? exprAny1 : exprAny2; + var resultIsBoolean1 = condObject ? exprBoolean1 : exprBoolean2; + var resultIsNumber1 = condObject ? exprNumber1 : exprNumber2; + var resultIsString1 = condObject ? exprString1 : exprString2; + var resultIsObject1 = condObject ? exprIsObject1 : exprIsObject2; + var resultIsStringOrBoolean1 = condObject ? exprString1 : exprBoolean1; // union + + var resultIsAny2 = ((a: string) => a.length) ? exprAny1 : exprAny2; + var resultIsBoolean2 = ((a: string) => a.length) ? exprBoolean1 : exprBoolean2; + var resultIsNumber2 = ({}) ? exprNumber1 : exprNumber2; + var resultIsString2 = ({ a: 1, b: "s" }) ? exprString1 : exprString2; + var resultIsObject2 = ({ a: 1, b: "s" }) ? exprIsObject1 : exprIsObject2; + var resultIsStringOrBoolean2 = ({ a: 1, b: "s" }) ? exprString1 : exprBoolean1; // union + + var resultIsAny3 = foo() ? exprAny1 : exprAny2; + ~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var resultIsBoolean3 = new Date() ? exprBoolean1 : exprBoolean2; + var resultIsNumber3 = new C() ? exprNumber1 : exprNumber2; + var resultIsString3 = C.doIt() ? exprString1 : exprString2; + ~~~~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var resultIsObject3 = condObject.valueOf() ? exprIsObject1 : exprIsObject2; + var resultIsStringOrBoolean3 = C.doIt() ? exprString1 : exprBoolean1; // union + ~~~~~~~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + \ No newline at end of file diff --git a/tests/baselines/reference/logicalAndOperatorStrictMode.errors.txt b/tests/baselines/reference/logicalAndOperatorStrictMode.errors.txt new file mode 100644 index 0000000000000..7534a33468a1f --- /dev/null +++ b/tests/baselines/reference/logicalAndOperatorStrictMode.errors.txt @@ -0,0 +1,107 @@ +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(46,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(47,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(48,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(49,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(50,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(51,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(52,12): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts(53,12): error TS1345: An expression of type 'void' cannot be tested for truthiness + + +==== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts (8 errors) ==== + const a = [0]; + const s = ""; + const x = 0; + const b = false; + const v: void = undefined; + const u = undefined; + const n = null; + const z = s || x || u; + + const a1 = a && a; + const a2 = a && s; + const a3 = a && x; + const a4 = a && b; + const a5 = a && v; + const a6 = a && u; + const a7 = a && n; + const a8 = a && z; + + const s1 = s && a; + const s2 = s && s; + const s3 = s && x; + const s4 = s && b; + const s5 = s && v; + const s6 = s && u; + const s7 = s && n; + const s8 = s && z; + + const x1 = x && a; + const x2 = x && s; + const x3 = x && x; + const x4 = x && b; + const x5 = x && v; + const x6 = x && u; + const x7 = x && n; + const x8 = x && z; + + const b1 = b && a; + const b2 = b && s; + const b3 = b && x; + const b4 = b && b; + const b5 = b && v; + const b6 = b && u; + const b7 = b && n; + const b8 = b && z; + + const v1 = v && a; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v2 = v && s; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v3 = v && x; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v4 = v && b; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v5 = v && v; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v6 = v && u; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v7 = v && n; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + const v8 = v && z; + ~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + + const u1 = u && a; + const u2 = u && s; + const u3 = u && x; + const u4 = u && b; + const u5 = u && v; + const u6 = u && u; + const u7 = u && n; + const u8 = u && z; + + const n1 = n && a; + const n2 = n && s; + const n3 = n && x; + const n4 = n && b; + const n5 = n && v; + const n6 = n && u; + const n7 = n && n; + const n8 = n && z; + + const z1 = z && a; + const z2 = z && s; + const z3 = z && x; + const z4 = z && b; + const z5 = z && v; + const z6 = z && u; + const z7 = z && n; + const z8 = z && z; \ No newline at end of file diff --git a/tests/baselines/reference/logicalAndOperatorWithEveryType.errors.txt b/tests/baselines/reference/logicalAndOperatorWithEveryType.errors.txt new file mode 100644 index 0000000000000..9c78f4a522f29 --- /dev/null +++ b/tests/baselines/reference/logicalAndOperatorWithEveryType.errors.txt @@ -0,0 +1,156 @@ +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(19,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(30,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(41,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(52,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(63,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(74,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(85,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(96,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(107,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts(118,11): error TS1345: An expression of type 'void' cannot be tested for truthiness + + +==== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorWithEveryType.ts (10 errors) ==== + // The && operator permits the operands to be of any type and produces a result of the same + // type as the second operand. + + enum E { a, b, c } + + var a1: any; + var a2: boolean; + var a3: number + var a4: string; + var a5: void; + var a6: E; + var a7: {}; + var a8: string[]; + + var ra1 = a1 && a1; + var ra2 = a2 && a1; + var ra3 = a3 && a1; + var ra4 = a4 && a1; + var ra5 = a5 && a1; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var ra6 = a6 && a1; + var ra7 = a7 && a1; + var ra8 = a8 && a1; + var ra9 = null && a1; + var ra10 = undefined && a1; + + var rb1 = a1 && a2; + var rb2 = a2 && a2; + var rb3 = a3 && a2; + var rb4 = a4 && a2; + var rb5 = a5 && a2; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rb6 = a6 && a2; + var rb7 = a7 && a2; + var rb8 = a8 && a2; + var rb9 = null && a2; + var rb10 = undefined && a2; + + var rc1 = a1 && a3; + var rc2 = a2 && a3; + var rc3 = a3 && a3; + var rc4 = a4 && a3; + var rc5 = a5 && a3; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rc6 = a6 && a3; + var rc7 = a7 && a3; + var rc8 = a8 && a3; + var rc9 = null && a3; + var rc10 = undefined && a3; + + var rd1 = a1 && a4; + var rd2 = a2 && a4; + var rd3 = a3 && a4; + var rd4 = a4 && a4; + var rd5 = a5 && a4; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rd6 = a6 && a4; + var rd7 = a7 && a4; + var rd8 = a8 && a4; + var rd9 = null && a4; + var rd10 = undefined && a4; + + var re1 = a1 && a5; + var re2 = a2 && a5; + var re3 = a3 && a5; + var re4 = a4 && a5; + var re5 = a5 && a5; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var re6 = a6 && a5; + var re7 = a7 && a5; + var re8 = a8 && a5; + var re9 = null && a5; + var re10 = undefined && a5; + + var rf1 = a1 && a6; + var rf2 = a2 && a6; + var rf3 = a3 && a6; + var rf4 = a4 && a6; + var rf5 = a5 && a6; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rf6 = a6 && a6; + var rf7 = a7 && a6; + var rf8 = a8 && a6; + var rf9 = null && a6; + var rf10 = undefined && a6; + + var rg1 = a1 && a7; + var rg2 = a2 && a7; + var rg3 = a3 && a7; + var rg4 = a4 && a7; + var rg5 = a5 && a7; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rg6 = a6 && a7; + var rg7 = a7 && a7; + var rg8 = a8 && a7; + var rg9 = null && a7; + var rg10 = undefined && a7; + + var rh1 = a1 && a8; + var rh2 = a2 && a8; + var rh3 = a3 && a8; + var rh4 = a4 && a8; + var rh5 = a5 && a8; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rh6 = a6 && a8; + var rh7 = a7 && a8; + var rh8 = a8 && a8; + var rh9 = null && a8; + var rh10 = undefined && a8; + + var ri1 = a1 && null; + var ri2 = a2 && null; + var ri3 = a3 && null; + var ri4 = a4 && null; + var ri5 = a5 && null; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var ri6 = a6 && null; + var ri7 = a7 && null; + var ri8 = a8 && null; + var ri9 = null && null; + var ri10 = undefined && null; + + var rj1 = a1 && undefined; + var rj2 = a2 && undefined; + var rj3 = a3 && undefined; + var rj4 = a4 && undefined; + var rj5 = a5 && undefined; + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rj6 = a6 && undefined; + var rj7 = a7 && undefined; + var rj8 = a8 && undefined; + var rj9 = null && undefined; + var rj10 = undefined && undefined; \ No newline at end of file diff --git a/tests/baselines/reference/logicalOrOperatorWithEveryType.errors.txt b/tests/baselines/reference/logicalOrOperatorWithEveryType.errors.txt new file mode 100644 index 0000000000000..8923186874c5e --- /dev/null +++ b/tests/baselines/reference/logicalOrOperatorWithEveryType.errors.txt @@ -0,0 +1,158 @@ +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(21,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(32,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(43,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(54,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(65,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(76,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(87,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(98,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(109,11): error TS1345: An expression of type 'void' cannot be tested for truthiness +tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts(120,11): error TS1345: An expression of type 'void' cannot be tested for truthiness + + +==== tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/logicalOrOperatorWithEveryType.ts (10 errors) ==== + // The || operator permits the operands to be of any type. + // If the || expression is not contextually typed, the right operand is contextually typed + // by the type of the left operand and the result is of the best common type of the two + // operand types. + + enum E { a, b, c } + + var a1: any; + var a2: boolean; + var a3: number + var a4: string; + var a5: void; + var a6: E; + var a7: {a: string}; + var a8: string[]; + + var ra1 = a1 || a1; // any || any is any + var ra2 = a2 || a1; // boolean || any is any + var ra3 = a3 || a1; // number || any is any + var ra4 = a4 || a1; // string || any is any + var ra5 = a5 || a1; // void || any is any + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var ra6 = a6 || a1; // enum || any is any + var ra7 = a7 || a1; // object || any is any + var ra8 = a8 || a1; // array || any is any + var ra9 = null || a1; // null || any is any + var ra10 = undefined || a1; // undefined || any is any + + var rb1 = a1 || a2; // any || boolean is any + var rb2 = a2 || a2; // boolean || boolean is boolean + var rb3 = a3 || a2; // number || boolean is number | boolean + var rb4 = a4 || a2; // string || boolean is string | boolean + var rb5 = a5 || a2; // void || boolean is void | boolean + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rb6 = a6 || a2; // enum || boolean is E | boolean + var rb7 = a7 || a2; // object || boolean is object | boolean + var rb8 = a8 || a2; // array || boolean is array | boolean + var rb9 = null || a2; // null || boolean is boolean + var rb10= undefined || a2; // undefined || boolean is boolean + + var rc1 = a1 || a3; // any || number is any + var rc2 = a2 || a3; // boolean || number is boolean | number + var rc3 = a3 || a3; // number || number is number + var rc4 = a4 || a3; // string || number is string | number + var rc5 = a5 || a3; // void || number is void | number + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rc6 = a6 || a3; // enum || number is number + var rc7 = a7 || a3; // object || number is object | number + var rc8 = a8 || a3; // array || number is array | number + var rc9 = null || a3; // null || number is number + var rc10 = undefined || a3; // undefined || number is number + + var rd1 = a1 || a4; // any || string is any + var rd2 = a2 || a4; // boolean || string is boolean | string + var rd3 = a3 || a4; // number || string is number | string + var rd4 = a4 || a4; // string || string is string + var rd5 = a5 || a4; // void || string is void | string + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rd6 = a6 || a4; // enum || string is enum | string + var rd7 = a7 || a4; // object || string is object | string + var rd8 = a8 || a4; // array || string is array | string + var rd9 = null || a4; // null || string is string + var rd10 = undefined || a4; // undefined || string is string + + var re1 = a1 || a5; // any || void is any + var re2 = a2 || a5; // boolean || void is boolean | void + var re3 = a3 || a5; // number || void is number | void + var re4 = a4 || a5; // string || void is string | void + var re5 = a5 || a5; // void || void is void + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var re6 = a6 || a5; // enum || void is enum | void + var re7 = a7 || a5; // object || void is object | void + var re8 = a8 || a5; // array || void is array | void + var re9 = null || a5; // null || void is void + var re10 = undefined || a5; // undefined || void is void + + var rg1 = a1 || a6; // any || enum is any + var rg2 = a2 || a6; // boolean || enum is boolean | enum + var rg3 = a3 || a6; // number || enum is number + var rg4 = a4 || a6; // string || enum is string | enum + var rg5 = a5 || a6; // void || enum is void | enum + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rg6 = a6 || a6; // enum || enum is E + var rg7 = a7 || a6; // object || enum is object | enum + var rg8 = a8 || a6; // array || enum is array | enum + var rg9 = null || a6; // null || enum is E + var rg10 = undefined || a6; // undefined || enum is E + + var rh1 = a1 || a7; // any || object is any + var rh2 = a2 || a7; // boolean || object is boolean | object + var rh3 = a3 || a7; // number || object is number | object + var rh4 = a4 || a7; // string || object is string | object + var rh5 = a5 || a7; // void || object is void | object + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rh6 = a6 || a7; // enum || object is enum | object + var rh7 = a7 || a7; // object || object is object + var rh8 = a8 || a7; // array || object is array | object + var rh9 = null || a7; // null || object is object + var rh10 = undefined || a7; // undefined || object is object + + var ri1 = a1 || a8; // any || array is any + var ri2 = a2 || a8; // boolean || array is boolean | array + var ri3 = a3 || a8; // number || array is number | array + var ri4 = a4 || a8; // string || array is string | array + var ri5 = a5 || a8; // void || array is void | array + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var ri6 = a6 || a8; // enum || array is enum | array + var ri7 = a7 || a8; // object || array is object | array + var ri8 = a8 || a8; // array || array is array + var ri9 = null || a8; // null || array is array + var ri10 = undefined || a8; // undefined || array is array + + var rj1 = a1 || null; // any || null is any + var rj2 = a2 || null; // boolean || null is boolean + var rj3 = a3 || null; // number || null is number + var rj4 = a4 || null; // string || null is string + var rj5 = a5 || null; // void || null is void + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rj6 = a6 || null; // enum || null is E + var rj7 = a7 || null; // object || null is object + var rj8 = a8 || null; // array || null is array + var rj9 = null || null; // null || null is any + var rj10 = undefined || null; // undefined || null is any + + var rf1 = a1 || undefined; // any || undefined is any + var rf2 = a2 || undefined; // boolean || undefined is boolean + var rf3 = a3 || undefined; // number || undefined is number + var rf4 = a4 || undefined; // string || undefined is string + var rf5 = a5 || undefined; // void || undefined is void + ~~ +!!! error TS1345: An expression of type 'void' cannot be tested for truthiness + var rf6 = a6 || undefined; // enum || undefined is E + var rf7 = a7 || undefined; // object || undefined is object + var rf8 = a8 || undefined; // array || undefined is array + var rf9 = null || undefined; // null || undefined is any + var rf10 = undefined || undefined; // undefined || undefined is any \ No newline at end of file