Merge pull request #11633 from Microsoft/fix-comparable-in-switch
Fix comparable in switch
This commit is contained in:
commit
6398e0d6dd
|
@ -16980,6 +16980,7 @@ namespace ts {
|
|||
let hasDuplicateDefaultClause = false;
|
||||
|
||||
const expressionType = checkExpression(node.expression);
|
||||
const expressionIsLiteral = isLiteralType(expressionType);
|
||||
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) {
|
||||
|
@ -17000,10 +17001,16 @@ 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);
|
||||
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
|
||||
let caseType = checkExpression(caseClause.expression);
|
||||
const caseIsLiteral = isLiteralType(caseType);
|
||||
let comparedExpressionType = expressionType;
|
||||
if (!caseIsLiteral || !expressionIsLiteral) {
|
||||
caseType = caseIsLiteral ? getBaseTypeOfLiteralType(caseType) : caseType;
|
||||
comparedExpressionType = getBaseTypeOfLiteralType(expressionType);
|
||||
}
|
||||
if (!isTypeEqualityComparableTo(comparedExpressionType, caseType)) {
|
||||
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
|
||||
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
|
||||
checkTypeComparableTo(caseType, comparedExpressionType, caseClause.expression, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
forEach(clause.statements, checkSourceElement);
|
||||
|
|
|
@ -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'.
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(4,10): error TS2678: Type 'typeof Foo' 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 '"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'.
|
||||
|
@ -10,11 +10,11 @@ tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: T
|
|||
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'.
|
||||
case 123: break; // No Error
|
||||
case 123: break; // Error
|
||||
~~~
|
||||
!!! error TS2678: Type '123' is not comparable to type '0'.
|
||||
case true: break; // Error
|
||||
|
@ -30,4 +30,5 @@ tests/cases/compiler/switchCasesExpressionTypeMismatch.ts(7,10): error TS2678: T
|
|||
case "sss": break;
|
||||
case 123: break;
|
||||
case true: break;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ class Foo { }
|
|||
switch (0) {
|
||||
case Foo: break; // Error
|
||||
case "sss": break; // Error
|
||||
case 123: break; // No Error
|
||||
case 123: break; // Error
|
||||
case true: break; // Error
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ switch (s) {
|
|||
case "sss": break;
|
||||
case 123: break;
|
||||
case true: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [switchCasesExpressionTypeMismatch.js]
|
||||
var Foo = (function () {
|
||||
|
@ -27,7 +28,7 @@ var Foo = (function () {
|
|||
switch (0) {
|
||||
case Foo: break; // Error
|
||||
case "sss": break; // Error
|
||||
case 123: break; // No Error
|
||||
case 123: break; // Error
|
||||
case true: break; // Error
|
||||
}
|
||||
var s = 0;
|
||||
|
|
29
tests/baselines/reference/switchComparableCompatForBrands.js
Normal file
29
tests/baselines/reference/switchComparableCompatForBrands.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
//// [switchComparableCompatForBrands.ts]
|
||||
class MyBrand
|
||||
{
|
||||
private _a: number;
|
||||
}
|
||||
|
||||
function test(strInput: string & MyBrand) {
|
||||
switch(strInput)
|
||||
{
|
||||
case "a":
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//// [switchComparableCompatForBrands.js]
|
||||
var MyBrand = (function () {
|
||||
function MyBrand() {
|
||||
}
|
||||
return MyBrand;
|
||||
}());
|
||||
function test(strInput) {
|
||||
switch (strInput) {
|
||||
case "a":
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
=== tests/cases/compiler/switchComparableCompatForBrands.ts ===
|
||||
class MyBrand
|
||||
>MyBrand : Symbol(MyBrand, Decl(switchComparableCompatForBrands.ts, 0, 0))
|
||||
{
|
||||
private _a: number;
|
||||
>_a : Symbol(MyBrand._a, Decl(switchComparableCompatForBrands.ts, 1, 1))
|
||||
}
|
||||
|
||||
function test(strInput: string & MyBrand) {
|
||||
>test : Symbol(test, Decl(switchComparableCompatForBrands.ts, 3, 1))
|
||||
>strInput : Symbol(strInput, Decl(switchComparableCompatForBrands.ts, 5, 14))
|
||||
>MyBrand : Symbol(MyBrand, Decl(switchComparableCompatForBrands.ts, 0, 0))
|
||||
|
||||
switch(strInput)
|
||||
>strInput : Symbol(strInput, Decl(switchComparableCompatForBrands.ts, 5, 14))
|
||||
{
|
||||
case "a":
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
=== tests/cases/compiler/switchComparableCompatForBrands.ts ===
|
||||
class MyBrand
|
||||
>MyBrand : MyBrand
|
||||
{
|
||||
private _a: number;
|
||||
>_a : number
|
||||
}
|
||||
|
||||
function test(strInput: string & MyBrand) {
|
||||
>test : (strInput: string & MyBrand) => 1 | 0
|
||||
>strInput : string & MyBrand
|
||||
>MyBrand : MyBrand
|
||||
|
||||
switch(strInput)
|
||||
>strInput : string & MyBrand
|
||||
{
|
||||
case "a":
|
||||
>"a" : "a"
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
}
|
||||
return 0;
|
||||
>0 : 0
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ class Foo { }
|
|||
switch (0) {
|
||||
case Foo: break; // Error
|
||||
case "sss": break; // Error
|
||||
case 123: break; // No Error
|
||||
case 123: break; // Error
|
||||
case true: break; // Error
|
||||
}
|
||||
|
||||
|
@ -15,4 +15,4 @@ switch (s) {
|
|||
case "sss": break;
|
||||
case 123: break;
|
||||
case true: break;
|
||||
}
|
||||
}
|
||||
|
|
13
tests/cases/compiler/switchComparableCompatForBrands.ts
Normal file
13
tests/cases/compiler/switchComparableCompatForBrands.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
class MyBrand
|
||||
{
|
||||
private _a: number;
|
||||
}
|
||||
|
||||
function test(strInput: string & MyBrand) {
|
||||
switch(strInput)
|
||||
{
|
||||
case "a":
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue