Merge pull request #5639 from Microsoft/typecheckStatementsInCaseClause

always check statements in case clause
This commit is contained in:
Vladimir Matveev
2015-11-12 13:11:57 -08:00
5 changed files with 106 additions and 6 deletions
+6 -6
View File
@@ -12886,13 +12886,13 @@ namespace ts {
// In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
const caseType = checkExpression(caseClause.expression);
// Permit 'number[] | "foo"' to be asserted to 'string'.
if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, TypeFlags.StringLike)) {
return;
}
const expressionTypeIsAssignableToCaseType =
// Permit 'number[] | "foo"' to be asserted to 'string'.
(expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, TypeFlags.StringLike)) ||
isTypeAssignableTo(expressionType, caseType);
if (!isTypeAssignableTo(expressionType, caseType)) {
// check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
if (!expressionTypeIsAssignableToCaseType) {
// 'expressionType is not assignable to caseType', try the reversed check and report errors if it fails
checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
}
}
@@ -0,0 +1,27 @@
//// [checkSwitchStatementIfCaseTypeIsString.ts]
declare function use(a: any): void;
class A {
doIt(x: Array<string>): void {
x.forEach((v) => {
switch(v) {
case "test": use(this);
}
});
}
}
//// [checkSwitchStatementIfCaseTypeIsString.js]
var A = (function () {
function A() {
}
A.prototype.doIt = function (x) {
var _this = this;
x.forEach(function (v) {
switch (v) {
case "test": use(_this);
}
});
};
return A;
})();
@@ -0,0 +1,29 @@
=== tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts ===
declare function use(a: any): void;
>use : Symbol(use, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 0))
>a : Symbol(a, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 21))
class A {
>A : Symbol(A, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 35))
doIt(x: Array<string>): void {
>doIt : Symbol(doIt, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 2, 9))
>x : Symbol(x, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 3, 9))
>Array : Symbol(Array, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
x.forEach((v) => {
>x.forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 3, 9))
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
>v : Symbol(v, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 4, 19))
switch(v) {
>v : Symbol(v, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 4, 19))
case "test": use(this);
>use : Symbol(use, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 0))
>this : Symbol(A, Decl(checkSwitchStatementIfCaseTypeIsString.ts, 0, 35))
}
});
}
}
@@ -0,0 +1,33 @@
=== tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts ===
declare function use(a: any): void;
>use : (a: any) => void
>a : any
class A {
>A : A
doIt(x: Array<string>): void {
>doIt : (x: string[]) => void
>x : string[]
>Array : T[]
x.forEach((v) => {
>x.forEach((v) => { switch(v) { case "test": use(this); } }) : void
>x.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
>x : string[]
>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
>(v) => { switch(v) { case "test": use(this); } } : (v: string) => void
>v : string
switch(v) {
>v : string
case "test": use(this);
>"test" : string
>use(this) : void
>use : (a: any) => void
>this : this
}
});
}
}
@@ -0,0 +1,11 @@
declare function use(a: any): void;
class A {
doIt(x: Array<string>): void {
x.forEach((v) => {
switch(v) {
case "test": use(this);
}
});
}
}