Skip to content

Commit ebef408

Browse files
committed
Move eitherIsNotLiteral check into switch and === checks
This improves error messages
1 parent b0080a2 commit ebef408

8 files changed

+43
-42
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13814,12 +13814,6 @@ namespace ts {
1381413814
}
1381513815

1381613816
function isTypeEqualityComparableTo(source: Type, target: Type) {
13817-
const sourceIsLiteral = isLiteralType(source);
13818-
const targetIsLiteral = isLiteralType(target);
13819-
if (!sourceIsLiteral || !targetIsLiteral) {
13820-
source = sourceIsLiteral ? getBaseTypeOfLiteralType(source) : source;
13821-
target = targetIsLiteral ? getBaseTypeOfLiteralType(target) : target;
13822-
}
1382313817
return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target);
1382413818
}
1382513819

@@ -13960,6 +13954,12 @@ namespace ts {
1396013954
case SyntaxKind.ExclamationEqualsToken:
1396113955
case SyntaxKind.EqualsEqualsEqualsToken:
1396213956
case SyntaxKind.ExclamationEqualsEqualsToken:
13957+
const leftIsLiteral = isLiteralType(leftType);
13958+
const rightIsLiteral = isLiteralType(rightType);
13959+
if (!leftIsLiteral || !rightIsLiteral) {
13960+
leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType;
13961+
rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType;
13962+
}
1396313963
if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) {
1396413964
reportOperatorError();
1396513965
}
@@ -16882,7 +16882,7 @@ namespace ts {
1688216882
let firstDefaultClause: CaseOrDefaultClause;
1688316883
let hasDuplicateDefaultClause = false;
1688416884

16885-
const expressionType = checkExpression(node.expression);
16885+
let expressionType = checkExpression(node.expression);
1688616886
forEach(node.caseBlock.clauses, clause => {
1688716887
// Grammar check for duplicate default clauses, skip if we already report duplicate default clause
1688816888
if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) {
@@ -16903,7 +16903,13 @@ namespace ts {
1690316903
// TypeScript 1.0 spec (April 2014): 5.9
1690416904
// In a 'switch' statement, each 'case' expression must be of a type that is comparable
1690516905
// to or from the type of the 'switch' expression.
16906-
const caseType = checkExpression(caseClause.expression);
16906+
let caseType = checkExpression(caseClause.expression);
16907+
const caseIsLiteral = isLiteralType(caseType);
16908+
const expressionIsLiteral = isLiteralType(expressionType);
16909+
if (!caseIsLiteral || !expressionIsLiteral) {
16910+
caseType = caseIsLiteral ? getBaseTypeOfLiteralType(caseType) : caseType;
16911+
expressionType = expressionIsLiteral ? getBaseTypeOfLiteralType(expressionType) : expressionType;
16912+
}
1690716913
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
1690816914
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
1690916915
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);

tests/baselines/reference/expr.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
tests/cases/compiler/expr.ts(87,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'string'.
2-
tests/cases/compiler/expr.ts(88,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'false'.
2+
tests/cases/compiler/expr.ts(88,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'boolean'.
33
tests/cases/compiler/expr.ts(94,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
4-
tests/cases/compiler/expr.ts(95,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'false'.
4+
tests/cases/compiler/expr.ts(95,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'boolean'.
55
tests/cases/compiler/expr.ts(98,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'E'.
66
tests/cases/compiler/expr.ts(115,5): error TS2365: Operator '==' cannot be applied to types 'E' and 'string'.
77
tests/cases/compiler/expr.ts(116,5): error TS2365: Operator '==' cannot be applied to types 'E' and 'false'.
@@ -161,7 +161,7 @@ tests/cases/compiler/expr.ts(242,7): error TS2363: The right-hand side of an ari
161161
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'string'.
162162
n==b;
163163
~~~~
164-
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'false'.
164+
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'boolean'.
165165
n==i;
166166
n==n;
167167
n==e;
@@ -172,7 +172,7 @@ tests/cases/compiler/expr.ts(242,7): error TS2363: The right-hand side of an ari
172172
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
173173
s==b;
174174
~~~~
175-
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'false'.
175+
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'boolean'.
176176
s==i;
177177
s==s;
178178
s==e;

tests/baselines/reference/for-inStatementsArrayErrors.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(5,14): error TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'.
22
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(6,16): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
3-
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(7,9): error TS2365: Operator '===' cannot be applied to types 'string' and '1'.
3+
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(7,9): error TS2365: Operator '===' cannot be applied to types 'string' and 'number'.
44
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(9,16): error TS2339: Property 'unknownProperty' does not exist on type 'string'.
55
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(13,10): error TS2403: Subsequent variable declarations must have the same type. Variable 'i' must be of type 'number', but here has type 'string'.
66
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(17,10): error TS2403: Subsequent variable declarations must have the same type. Variable 'j' must be of type 'any', but here has type 'string'.
@@ -19,7 +19,7 @@ tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.
1919
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
2020
if (x === 1) {
2121
~~~~~~~
22-
!!! error TS2365: Operator '===' cannot be applied to types 'string' and '1'.
22+
!!! error TS2365: Operator '===' cannot be applied to types 'string' and 'number'.
2323
}
2424
let a3 = x.unknownProperty;
2525
~~~~~~~~~~~~~~~

tests/baselines/reference/stringLiteralsAssertionsInEqualityComparisons02.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(3,9): error TS2365: Operator '===' cannot be applied to types '"foo"' and '"baz"'.
2-
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,9): error TS2365: Operator '==' cannot be applied to types '"foo"' and 'number'.
2+
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,9): error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
33
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,19): error TS2352: Type 'string' cannot be converted to type 'number'.
44

55

@@ -12,7 +12,7 @@ tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparis
1212
var b = "foo" !== ("bar" as "foo");
1313
var c = "foo" == (<number>"bar");
1414
~~~~~~~~~~~~~~~~~~~~~~~~
15-
!!! error TS2365: Operator '==' cannot be applied to types '"foo"' and 'number'.
15+
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
1616
~~~~~~~~~~~~~
1717
!!! error TS2352: Type 'string' cannot be converted to type 'number'.
1818
var d = "foo" === ("bar" as EnhancedString);
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type '0'.
1+
tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
22

33

44
==== tests/cases/compiler/switchAssignmentCompat.ts (1 errors) ====
@@ -7,6 +7,6 @@ tests/cases/compiler/switchAssignmentCompat.ts(4,10): error TS2678: Type 'typeof
77
switch (0) {
88
case Foo: break; // Error expected
99
~~~
10-
!!! error TS2678: Type 'typeof Foo' is not comparable to type '0'.
10+
!!! error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
1111
}
1212

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
tests/cases/compiler/switchCaseCircularRefeference.ts(5,10): error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
2-
Type '{ a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
3-
Type '{ a: "C"; e: any; }' is not comparable to type '"C"'.
1+
tests/cases/compiler/switchCaseCircularRefeference.ts(5,10): error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type 'string'.
2+
Type '{ a: "C"; e: any; }' is not comparable to type 'string'.
43

54

65
==== tests/cases/compiler/switchCaseCircularRefeference.ts (1 errors) ====
@@ -10,9 +9,8 @@ tests/cases/compiler/switchCaseCircularRefeference.ts(5,10): error TS2678: Type
109
switch (x.a) {
1110
case x:
1211
~
13-
!!! error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
14-
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
15-
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type '"C"'.
12+
!!! error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type 'string'.
13+
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type 'string'.
1614
break;
1715
}
1816
}

tests/baselines/reference/switchCasesExpressionTypeMismatch.errors.txt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
1-
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type '0'.
2-
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2678: Type '"sss"' is not comparable to type '0'.
3-
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(6,10): error TS2678: Type '123' is not comparable to type '0'.
4-
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: Type 'true' is not comparable to type '0'.
1+
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
2+
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2678: Type 'string' is not comparable to type 'number'.
3+
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: Type 'boolean' is not comparable to type 'number'.
54

65

7-
==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (4 errors) ====
6+
==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (3 errors) ====
87
class Foo { }
98

109
switch (0) {
1110
case Foo: break; // Error
1211
~~~
13-
!!! error TS2678: Type 'typeof Foo' is not comparable to type '0'.
12+
!!! error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
1413
case "sss": break; // Error
1514
~~~~~
16-
!!! error TS2678: Type '"sss"' is not comparable to type '0'.
15+
!!! error TS2678: Type 'string' is not comparable to type 'number'.
1716
case 123: break; // No Error
18-
~~~
19-
!!! error TS2678: Type '123' is not comparable to type '0'.
2017
case true: break; // Error
2118
~~~~
22-
!!! error TS2678: Type 'true' is not comparable to type '0'.
19+
!!! error TS2678: Type 'boolean' is not comparable to type 'number'.
2320
}
2421

2522
var s: any = 0;
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
tests/cases/conformance/es6/Symbols/symbolType9.ts(3,1): error TS2365: Operator '==' cannot be applied to types 'symbol' and 'true'.
2-
tests/cases/conformance/es6/Symbols/symbolType9.ts(5,1): error TS2365: Operator '!=' cannot be applied to types '0' and 'symbol'.
3-
tests/cases/conformance/es6/Symbols/symbolType9.ts(7,1): error TS2365: Operator '===' cannot be applied to types 'symbol' and '1'.
4-
tests/cases/conformance/es6/Symbols/symbolType9.ts(9,1): error TS2365: Operator '!==' cannot be applied to types 'false' and 'symbol'.
1+
tests/cases/conformance/es6/Symbols/symbolType9.ts(3,1): error TS2365: Operator '==' cannot be applied to types 'symbol' and 'boolean'.
2+
tests/cases/conformance/es6/Symbols/symbolType9.ts(5,1): error TS2365: Operator '!=' cannot be applied to types 'number' and 'symbol'.
3+
tests/cases/conformance/es6/Symbols/symbolType9.ts(7,1): error TS2365: Operator '===' cannot be applied to types 'symbol' and 'number'.
4+
tests/cases/conformance/es6/Symbols/symbolType9.ts(9,1): error TS2365: Operator '!==' cannot be applied to types 'boolean' and 'symbol'.
55

66

77
==== tests/cases/conformance/es6/Symbols/symbolType9.ts (4 errors) ====
88
var s = Symbol.for("equal");
99
s == s;
1010
s == true;
1111
~~~~~~~~~
12-
!!! error TS2365: Operator '==' cannot be applied to types 'symbol' and 'true'.
12+
!!! error TS2365: Operator '==' cannot be applied to types 'symbol' and 'boolean'.
1313
s != s;
1414
0 != s;
1515
~~~~~~
16-
!!! error TS2365: Operator '!=' cannot be applied to types '0' and 'symbol'.
16+
!!! error TS2365: Operator '!=' cannot be applied to types 'number' and 'symbol'.
1717
s === s;
1818
s === 1;
1919
~~~~~~~
20-
!!! error TS2365: Operator '===' cannot be applied to types 'symbol' and '1'.
20+
!!! error TS2365: Operator '===' cannot be applied to types 'symbol' and 'number'.
2121
s !== s;
2222
false !== s;
2323
~~~~~~~~~~~
24-
!!! error TS2365: Operator '!==' cannot be applied to types 'false' and 'symbol'.
24+
!!! error TS2365: Operator '!==' cannot be applied to types 'boolean' and 'symbol'.

0 commit comments

Comments
 (0)