Move eitherIsNotLiteral check into switch and === checks

This improves error messages
This commit is contained in:
Nathan Shively-Sanders 2016-10-31 14:44:04 -07:00
parent b0080a253d
commit ebef408dfa
8 changed files with 43 additions and 42 deletions

View file

@ -13814,12 +13814,6 @@ namespace ts {
}
function isTypeEqualityComparableTo(source: Type, target: Type) {
const sourceIsLiteral = isLiteralType(source);
const targetIsLiteral = isLiteralType(target);
if (!sourceIsLiteral || !targetIsLiteral) {
source = sourceIsLiteral ? getBaseTypeOfLiteralType(source) : source;
target = targetIsLiteral ? getBaseTypeOfLiteralType(target) : target;
}
return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target);
}
@ -13960,6 +13954,12 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
const leftIsLiteral = isLiteralType(leftType);
const rightIsLiteral = isLiteralType(rightType);
if (!leftIsLiteral || !rightIsLiteral) {
leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType;
rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType;
}
if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) {
reportOperatorError();
}
@ -16882,7 +16882,7 @@ namespace ts {
let firstDefaultClause: CaseOrDefaultClause;
let hasDuplicateDefaultClause = false;
const expressionType = checkExpression(node.expression);
let expressionType = checkExpression(node.expression);
forEach(node.caseBlock.clauses, clause => {
// Grammar check for duplicate default clauses, skip if we already report duplicate default clause
if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) {
@ -16903,7 +16903,13 @@ namespace ts {
// TypeScript 1.0 spec (April 2014): 5.9
// In a 'switch' statement, each 'case' expression must be of a type that is comparable
// to or from the type of the 'switch' expression.
const caseType = checkExpression(caseClause.expression);
let caseType = checkExpression(caseClause.expression);
const caseIsLiteral = isLiteralType(caseType);
const expressionIsLiteral = isLiteralType(expressionType);
if (!caseIsLiteral || !expressionIsLiteral) {
caseType = caseIsLiteral ? getBaseTypeOfLiteralType(caseType) : caseType;
expressionType = expressionIsLiteral ? getBaseTypeOfLiteralType(expressionType) : expressionType;
}
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);

View file

@ -1,7 +1,7 @@
tests/cases/compiler/expr.ts(87,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'string'.
tests/cases/compiler/expr.ts(88,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'false'.
tests/cases/compiler/expr.ts(88,5): error TS2365: Operator '==' cannot be applied to types 'number' and 'boolean'.
tests/cases/compiler/expr.ts(94,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
tests/cases/compiler/expr.ts(95,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'false'.
tests/cases/compiler/expr.ts(95,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'boolean'.
tests/cases/compiler/expr.ts(98,5): error TS2365: Operator '==' cannot be applied to types 'string' and 'E'.
tests/cases/compiler/expr.ts(115,5): error TS2365: Operator '==' cannot be applied to types 'E' and 'string'.
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
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'string'.
n==b;
~~~~
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'false'.
!!! error TS2365: Operator '==' cannot be applied to types 'number' and 'boolean'.
n==i;
n==n;
n==e;
@ -172,7 +172,7 @@ tests/cases/compiler/expr.ts(242,7): error TS2363: The right-hand side of an ari
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
s==b;
~~~~
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'false'.
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'boolean'.
s==i;
s==s;
s==e;

View file

@ -1,6 +1,6 @@
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'.
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.
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(7,9): error TS2365: Operator '===' cannot be applied to types 'string' and '1'.
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(7,9): error TS2365: Operator '===' cannot be applied to types 'string' and 'number'.
tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts(9,16): error TS2339: Property 'unknownProperty' does not exist on type 'string'.
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'.
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.
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
if (x === 1) {
~~~~~~~
!!! error TS2365: Operator '===' cannot be applied to types 'string' and '1'.
!!! error TS2365: Operator '===' cannot be applied to types 'string' and 'number'.
}
let a3 = x.unknownProperty;
~~~~~~~~~~~~~~~

View file

@ -1,5 +1,5 @@
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(3,9): error TS2365: Operator '===' cannot be applied to types '"foo"' and '"baz"'.
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,9): error TS2365: Operator '==' cannot be applied to types '"foo"' and 'number'.
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,9): error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparisons02.ts(5,19): error TS2352: Type 'string' cannot be converted to type 'number'.
@ -12,7 +12,7 @@ tests/cases/conformance/types/literal/stringLiteralsAssertionsInEqualityComparis
var b = "foo" !== ("bar" as "foo");
var c = "foo" == (<number>"bar");
~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2365: Operator '==' cannot be applied to types '"foo"' and 'number'.
!!! error TS2365: Operator '==' cannot be applied to types 'string' and 'number'.
~~~~~~~~~~~~~
!!! error TS2352: Type 'string' cannot be converted to type 'number'.
var d = "foo" === ("bar" as EnhancedString);

View file

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

View file

@ -1,6 +1,5 @@
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"'.
Type '{ a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
Type '{ a: "C"; e: any; }' is not comparable to type '"C"'.
tests/cases/compiler/switchCaseCircularRefeference.ts(5,10): error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type 'string'.
Type '{ a: "C"; e: any; }' is not comparable to type 'string'.
==== tests/cases/compiler/switchCaseCircularRefeference.ts (1 errors) ====
@ -10,9 +9,8 @@ tests/cases/compiler/switchCaseCircularRefeference.ts(5,10): error TS2678: Type
switch (x.a) {
case x:
~
!!! error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type '"A" | "C"'.
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type '"C"'.
!!! error TS2678: Type '{ a: "A"; b: any; } | { a: "C"; e: any; }' is not comparable to type 'string'.
!!! error TS2678: Type '{ a: "C"; e: any; }' is not comparable to type 'string'.
break;
}
}

View file

@ -1,25 +1,22 @@
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type '0'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2678: Type '"sss"' is not comparable to type '0'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(6,10): error TS2678: Type '123' is not comparable to type '0'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: Type 'true' is not comparable to type '0'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(5,10): error TS2678: Type 'string' is not comparable to type 'number'.
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: Type 'boolean' is not comparable to type 'number'.
==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (4 errors) ====
==== tests/cases/compiler/switchCasesExpressionTypeMismatch.ts (3 errors) ====
class Foo { }
switch (0) {
case Foo: break; // Error
~~~
!!! error TS2678: Type 'typeof Foo' is not comparable to type '0'.
!!! error TS2678: Type 'typeof Foo' is not comparable to type 'number'.
case "sss": break; // Error
~~~~~
!!! error TS2678: Type '"sss"' is not comparable to type '0'.
!!! error TS2678: Type 'string' is not comparable to type 'number'.
case 123: break; // No Error
~~~
!!! error TS2678: Type '123' is not comparable to type '0'.
case true: break; // Error
~~~~
!!! error TS2678: Type 'true' is not comparable to type '0'.
!!! error TS2678: Type 'boolean' is not comparable to type 'number'.
}
var s: any = 0;

View file

@ -1,7 +1,7 @@
tests/cases/conformance/es6/Symbols/symbolType9.ts(3,1): error TS2365: Operator '==' cannot be applied to types 'symbol' and 'true'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(5,1): error TS2365: Operator '!=' cannot be applied to types '0' and 'symbol'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(7,1): error TS2365: Operator '===' cannot be applied to types 'symbol' and '1'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(9,1): error TS2365: Operator '!==' cannot be applied to types 'false' and 'symbol'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(3,1): error TS2365: Operator '==' cannot be applied to types 'symbol' and 'boolean'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(5,1): error TS2365: Operator '!=' cannot be applied to types 'number' and 'symbol'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(7,1): error TS2365: Operator '===' cannot be applied to types 'symbol' and 'number'.
tests/cases/conformance/es6/Symbols/symbolType9.ts(9,1): error TS2365: Operator '!==' cannot be applied to types 'boolean' and 'symbol'.
==== tests/cases/conformance/es6/Symbols/symbolType9.ts (4 errors) ====
@ -9,16 +9,16 @@ tests/cases/conformance/es6/Symbols/symbolType9.ts(9,1): error TS2365: Operator
s == s;
s == true;
~~~~~~~~~
!!! error TS2365: Operator '==' cannot be applied to types 'symbol' and 'true'.
!!! error TS2365: Operator '==' cannot be applied to types 'symbol' and 'boolean'.
s != s;
0 != s;
~~~~~~
!!! error TS2365: Operator '!=' cannot be applied to types '0' and 'symbol'.
!!! error TS2365: Operator '!=' cannot be applied to types 'number' and 'symbol'.
s === s;
s === 1;
~~~~~~~
!!! error TS2365: Operator '===' cannot be applied to types 'symbol' and '1'.
!!! error TS2365: Operator '===' cannot be applied to types 'symbol' and 'number'.
s !== s;
false !== s;
~~~~~~~~~~~
!!! error TS2365: Operator '!==' cannot be applied to types 'false' and 'symbol'.
!!! error TS2365: Operator '!==' cannot be applied to types 'boolean' and 'symbol'.