diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7856e3f4cda92..a215eda64c1e7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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); } } diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js new file mode 100644 index 0000000000000..64ea4e67fa8a7 --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.js @@ -0,0 +1,27 @@ +//// [checkSwitchStatementIfCaseTypeIsString.ts] +declare function use(a: any): void; + +class A { + doIt(x: Array): 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; +})(); diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols new file mode 100644 index 0000000000000..6bc994f2a449f --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.symbols @@ -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): 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)) + } + }); + } +} diff --git a/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types new file mode 100644 index 0000000000000..fa394b4e0bd32 --- /dev/null +++ b/tests/baselines/reference/checkSwitchStatementIfCaseTypeIsString.types @@ -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): 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 + } + }); + } +} diff --git a/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts b/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts new file mode 100644 index 0000000000000..931f64a4b2957 --- /dev/null +++ b/tests/cases/compiler/checkSwitchStatementIfCaseTypeIsString.ts @@ -0,0 +1,11 @@ +declare function use(a: any): void; + +class A { + doIt(x: Array): void { + x.forEach((v) => { + switch(v) { + case "test": use(this); + } + }); + } +} \ No newline at end of file