Fix fallthrough and default in new switch-true narrowing (#55991)

This commit is contained in:
Jake Bailey
2023-10-06 16:23:54 -07:00
committed by GitHub
parent 2e58032f06
commit 53a3d24b95
35 changed files with 3119 additions and 151 deletions
+31 -5
View File
@@ -27456,11 +27456,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
type = narrowTypeBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
else if (expr.kind === SyntaxKind.TrueKeyword) {
const clause = flow.switchStatement.caseBlock.clauses.find((_, index) => index === flow.clauseStart);
const clauseExpression = clause && clause.kind === SyntaxKind.CaseClause ? clause.expression : undefined;
if (clauseExpression) {
type = narrowType(type, clauseExpression, /*assumeTrue*/ true);
}
type = narrowTypeBySwitchOnTrue(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
}
else {
if (strictNullChecks) {
@@ -28075,6 +28071,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return getUnionType(map(clauseWitnesses, text => text ? narrowTypeByTypeName(type, text) : neverType));
}
function narrowTypeBySwitchOnTrue(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type {
const defaultIndex = findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.DefaultClause);
const hasDefaultClause = clauseStart === clauseEnd || (defaultIndex >= clauseStart && defaultIndex < clauseEnd);
// First, narrow away all of the cases that preceded this set of cases.
for (let i = 0; i < clauseStart; i++) {
const clause = switchStatement.caseBlock.clauses[i];
if (clause.kind === SyntaxKind.CaseClause) {
type = narrowType(type, clause.expression, /*assumeTrue*/ false);
}
}
// If our current set has a default, then none the other cases were hit either.
// There's no point in narrowing by the the other cases in the set, since we can
// get here through other paths.
if (hasDefaultClause) {
for (let i = clauseEnd; i < switchStatement.caseBlock.clauses.length; i++) {
const clause = switchStatement.caseBlock.clauses[i];
if (clause.kind === SyntaxKind.CaseClause) {
type = narrowType(type, clause.expression, /*assumeTrue*/ false);
}
}
return type;
}
// Now, narrow based on the cases in this set.
const clauses = switchStatement.caseBlock.clauses.slice(clauseStart, clauseEnd);
return getUnionType(map(clauses, clause => clause.kind === SyntaxKind.CaseClause ? narrowType(type, clause.expression, /*assumeTrue*/ true) : neverType));
}
function isMatchingConstructorReference(expr: Expression) {
return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" ||
isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") &&
@@ -1,144 +0,0 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue.ts] ////
=== narrowByClauseExpressionInSwitchTrue.ts ===
// https://github.com/microsoft/TypeScript/issues/37178
type A = { type: "A" };
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue.ts, 0, 0))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 10))
type B = { type: "B" };
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 23))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 10))
type AorB = A | B;
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 23))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue.ts, 0, 0))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 23))
const isA = (x: AorB): x is A => x.type === "A";
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 13))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 23))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 13))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue.ts, 0, 0))
>x.type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 10))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 13))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 10))
const isB = (x: AorB): x is B => x.type === "B";
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 13))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 23))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 13))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 23))
>x.type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 10))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 13))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 10))
function test1(x: AorB) {
>test1 : Symbol(test1, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 48))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 9, 15))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 23))
switch (true) {
case isA(x):
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 9, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 9, 15))
break;
case isB(x):
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 9, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 9, 15))
break;
}
}
function test2(x: AorB) {
>test2 : Symbol(test2, Decl(narrowByClauseExpressionInSwitchTrue.ts, 18, 1))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 20, 15))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 3, 23))
switch (true) {
case isA(x):
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 20, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 20, 15))
// fallthrough
case isB(x):
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 20, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 20, 15))
break;
}
}
let x: string | undefined;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 31, 3))
switch (true) {
case typeof x !== "undefined":
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 31, 3))
x.trim();
>x.trim : Symbol(String.trim, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 31, 3))
>trim : Symbol(String.trim, Decl(lib.es5.d.ts, --, --))
}
type SomeType = { type: "SomeType" };
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue.ts, 36, 1))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue.ts, 38, 17))
declare function isSomeType(x: unknown): x is SomeType;
>isSomeType : Symbol(isSomeType, Decl(narrowByClauseExpressionInSwitchTrue.ts, 38, 37))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 39, 28))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue.ts, 39, 28))
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue.ts, 36, 1))
function processInput(input: string | RegExp | SomeType) {
>processInput : Symbol(processInput, Decl(narrowByClauseExpressionInSwitchTrue.ts, 39, 55))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue.ts, 36, 1))
switch (true) {
case typeof input === "string":
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
break;
case input instanceof RegExp:
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
break;
case isSomeType(input):
>isSomeType : Symbol(isSomeType, Decl(narrowByClauseExpressionInSwitchTrue.ts, 38, 37))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue.ts, 41, 22))
break;
}
}
@@ -0,0 +1,144 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue1.ts] ////
=== narrowByClauseExpressionInSwitchTrue1.ts ===
// https://github.com/microsoft/TypeScript/issues/37178
type A = { type: "A" };
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 0, 0))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 10))
type B = { type: "B" };
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 23))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 10))
type AorB = A | B;
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 23))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 0, 0))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 23))
const isA = (x: AorB): x is A => x.type === "A";
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 13))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 23))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 13))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 0, 0))
>x.type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 10))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 13))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 10))
const isB = (x: AorB): x is B => x.type === "B";
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 13))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 23))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 13))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 23))
>x.type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 10))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 13))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 10))
function test1(x: AorB) {
>test1 : Symbol(test1, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 48))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 9, 15))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 23))
switch (true) {
case isA(x):
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 9, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 9, 15))
break;
case isB(x):
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 9, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 9, 15))
break;
}
}
function test2(x: AorB) {
>test2 : Symbol(test2, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 18, 1))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 20, 15))
>AorB : Symbol(AorB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 3, 23))
switch (true) {
case isA(x):
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 6, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 20, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 20, 15))
// fallthrough
case isB(x):
>isB : Symbol(isB, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 7, 5))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 20, 15))
x;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 20, 15))
break;
}
}
let x: string | undefined;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 31, 3))
switch (true) {
case typeof x !== "undefined":
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 31, 3))
x.trim();
>x.trim : Symbol(String.trim, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 31, 3))
>trim : Symbol(String.trim, Decl(lib.es5.d.ts, --, --))
}
type SomeType = { type: "SomeType" };
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 36, 1))
>type : Symbol(type, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 38, 17))
declare function isSomeType(x: unknown): x is SomeType;
>isSomeType : Symbol(isSomeType, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 38, 37))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 39, 28))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 39, 28))
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 36, 1))
function processInput(input: string | RegExp | SomeType) {
>processInput : Symbol(processInput, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 39, 55))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>SomeType : Symbol(SomeType, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 36, 1))
switch (true) {
case typeof input === "string":
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
break;
case input instanceof RegExp:
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
>RegExp : Symbol(RegExp, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
break;
case isSomeType(input):
>isSomeType : Symbol(isSomeType, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 38, 37))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
input;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue1.ts, 41, 22))
break;
}
}
@@ -1,6 +1,6 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue.ts] ////
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue1.ts] ////
=== narrowByClauseExpressionInSwitchTrue.ts ===
=== narrowByClauseExpressionInSwitchTrue1.ts ===
// https://github.com/microsoft/TypeScript/issues/37178
type A = { type: "A" };
@@ -0,0 +1,107 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue10.ts] ////
=== narrowByClauseExpressionInSwitchTrue10.ts ===
function foo(cond1: boolean, cond2: boolean) {
>foo : Symbol(foo, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 0))
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
switch (true) {
case cond1 || cond2:
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
cond1; // boolean
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
// ^?
cond2; // boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
// ^?
break;
case cond2:
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
cond1; // false
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
// ^?
cond2;; // never
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
// ^?
break;
default:
cond1; // false
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
// ^?
cond2; // false
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
// ^?
break;
}
cond1; // boolean
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 13))
// ^?
cond2; // boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 0, 28))
// ^?
}
function blah(cond1: boolean, cond2: boolean) {
>blah : Symbol(blah, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 28, 1))
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
if (cond1 || cond2) {
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
cond1; // boolean
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
// ^?
cond2; // boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
// ^?
} else if (cond2) {
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
cond1; // false
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
// ^?
cond2; // never
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
// ^?
} else {
cond1; // false
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
// ^?
cond2; // false
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
// ^?
}
cond1; // boolean
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 14))
// ^?
cond2; // boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue10.ts, 30, 29))
// ^?
}
@@ -0,0 +1,111 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue10.ts] ////
=== narrowByClauseExpressionInSwitchTrue10.ts ===
function foo(cond1: boolean, cond2: boolean) {
>foo : (cond1: boolean, cond2: boolean) => void
>cond1 : boolean
>cond2 : boolean
switch (true) {
>true : true
case cond1 || cond2:
>cond1 || cond2 : boolean
>cond1 : boolean
>cond2 : boolean
cond1; // boolean
>cond1 : boolean
// ^?
cond2; // boolean
>cond2 : boolean
// ^?
break;
case cond2:
>cond2 : boolean
cond1; // false
>cond1 : false
// ^?
cond2;; // never
>cond2 : never
// ^?
break;
default:
cond1; // false
>cond1 : false
// ^?
cond2; // false
>cond2 : false
// ^?
break;
}
cond1; // boolean
>cond1 : boolean
// ^?
cond2; // boolean
>cond2 : boolean
// ^?
}
function blah(cond1: boolean, cond2: boolean) {
>blah : (cond1: boolean, cond2: boolean) => void
>cond1 : boolean
>cond2 : boolean
if (cond1 || cond2) {
>cond1 || cond2 : boolean
>cond1 : boolean
>cond2 : boolean
cond1; // boolean
>cond1 : boolean
// ^?
cond2; // boolean
>cond2 : boolean
// ^?
} else if (cond2) {
>cond2 : false
cond1; // false
>cond1 : false
// ^?
cond2; // never
>cond2 : never
// ^?
} else {
cond1; // false
>cond1 : false
// ^?
cond2; // false
>cond2 : false
// ^?
}
cond1; // boolean
>cond1 : boolean
// ^?
cond2; // boolean
>cond2 : boolean
// ^?
}
@@ -0,0 +1,49 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue2.ts] ////
=== narrowByClauseExpressionInSwitchTrue2.ts ===
// https://github.com/microsoft/TypeScript/issues/55986
declare const f: 'a' | 'b' | 'c';
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
switch(true) {
case f === 'a':
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
case f === 'b':
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
break
default:
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
}
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
switch(true) {
case f === 'a':
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
case f === 'b':
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
break
default:
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
}
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue2.ts, 2, 13))
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue2.ts] ////
=== narrowByClauseExpressionInSwitchTrue2.ts ===
// https://github.com/microsoft/TypeScript/issues/55986
declare const f: 'a' | 'b' | 'c';
>f : "a" | "b" | "c"
switch(true) {
>true : true
case f === 'a':
>f === 'a' : boolean
>f : "a" | "b" | "c"
>'a' : "a"
case f === 'b':
>f === 'b' : boolean
>f : "a" | "b" | "c"
>'b' : "b"
f;
>f : "a" | "b"
break
default:
f;
>f : "c"
}
f;
>f : "a" | "b" | "c"
switch(true) {
>true : true
case f === 'a':
>f === 'a' : boolean
>f : "a" | "b" | "c"
>'a' : "a"
f;
>f : "a"
case f === 'b':
>f === 'b' : boolean
>f : "a" | "b" | "c"
>'b' : "b"
f;
>f : "a" | "b"
break
default:
f;
>f : "c"
}
f;
>f : "a" | "b" | "c"
@@ -0,0 +1,32 @@
narrowByClauseExpressionInSwitchTrue3.ts(12,9): error TS2367: This comparison appears to be unintentional because the types '"square"' and '"circle"' have no overlap.
narrowByClauseExpressionInSwitchTrue3.ts(13,32): error TS2339: Property 'radius' does not exist on type 'never'.
narrowByClauseExpressionInSwitchTrue3.ts(15,14): error TS2367: This comparison appears to be unintentional because the types '"square"' and '"circle"' have no overlap.
==== narrowByClauseExpressionInSwitchTrue3.ts (3 errors) ====
type Shape =
| { kind: "circle", radius: number }
| { kind: "square", sideLength: number }
function wat(shape: Shape) {
switch (true) {
case shape.kind === "circle":
return Math.PI * shape.radius ** 2;
case shape.kind === "circle": // should error
}
if (shape.kind === "circle") {
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2367: This comparison appears to be unintentional because the types '"square"' and '"circle"' have no overlap.
return Math.PI * shape.radius ** 2;
~~~~~~
!!! error TS2339: Property 'radius' does not exist on type 'never'.
}
else if (shape.kind === "circle") {
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2367: This comparison appears to be unintentional because the types '"square"' and '"circle"' have no overlap.
// ~~~~
// Property 'kind' does not exist on type 'never'.
}
}
@@ -0,0 +1,60 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue3.ts] ////
=== narrowByClauseExpressionInSwitchTrue3.ts ===
type Shape =
>Shape : Symbol(Shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 0, 0))
| { kind: "circle", radius: number }
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 7))
>radius : Symbol(radius, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 23))
| { kind: "square", sideLength: number }
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
>sideLength : Symbol(sideLength, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 23))
function wat(shape: Shape) {
>wat : Symbol(wat, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 44))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>Shape : Symbol(Shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 0, 0))
switch (true) {
case shape.kind === "circle":
>shape.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 7), Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 7), Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
return Math.PI * shape.radius ** 2;
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>shape.radius : Symbol(radius, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 23))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>radius : Symbol(radius, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 23))
case shape.kind === "circle": // should error
>shape.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 7), Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 1, 7), Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
}
if (shape.kind === "circle") {
>shape.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
return Math.PI * shape.radius ** 2;
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
}
else if (shape.kind === "circle") {
>shape.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
>shape : Symbol(shape, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 4, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue3.ts, 2, 7))
// ~~~~
// Property 'kind' does not exist on type 'never'.
}
}
@@ -0,0 +1,77 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue3.ts] ////
=== narrowByClauseExpressionInSwitchTrue3.ts ===
type Shape =
>Shape : { kind: "circle"; radius: number; } | { kind: "square"; sideLength: number; }
| { kind: "circle", radius: number }
>kind : "circle"
>radius : number
| { kind: "square", sideLength: number }
>kind : "square"
>sideLength : number
function wat(shape: Shape) {
>wat : (shape: Shape) => number | undefined
>shape : Shape
switch (true) {
>true : true
case shape.kind === "circle":
>shape.kind === "circle" : boolean
>shape.kind : "circle" | "square"
>shape : Shape
>kind : "circle" | "square"
>"circle" : "circle"
return Math.PI * shape.radius ** 2;
>Math.PI * shape.radius ** 2 : number
>Math.PI : number
>Math : Math
>PI : number
>shape.radius ** 2 : number
>shape.radius : number
>shape : { kind: "circle"; radius: number; }
>radius : number
>2 : 2
case shape.kind === "circle": // should error
>shape.kind === "circle" : boolean
>shape.kind : "circle" | "square"
>shape : Shape
>kind : "circle" | "square"
>"circle" : "circle"
}
if (shape.kind === "circle") {
>shape.kind === "circle" : boolean
>shape.kind : "square"
>shape : { kind: "square"; sideLength: number; }
>kind : "square"
>"circle" : "circle"
return Math.PI * shape.radius ** 2;
>Math.PI * shape.radius ** 2 : number
>Math.PI : number
>Math : Math
>PI : number
>shape.radius ** 2 : number
>shape.radius : any
>shape : never
>radius : any
>2 : 2
}
else if (shape.kind === "circle") {
>shape.kind === "circle" : boolean
>shape.kind : "square"
>shape : { kind: "square"; sideLength: number; }
>kind : "square"
>"circle" : "circle"
// ~~~~
// Property 'kind' does not exist on type 'never'.
}
}
@@ -0,0 +1,21 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue4.ts] ////
=== narrowByClauseExpressionInSwitchTrue4.ts ===
declare const f: 'a' | 'b' | 'c';
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue4.ts, 0, 13))
switch (true) {
case f === "a":
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue4.ts, 0, 13))
default:
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue4.ts, 0, 13))
case f === "b":
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue4.ts, 0, 13))
f;
>f : Symbol(f, Decl(narrowByClauseExpressionInSwitchTrue4.ts, 0, 13))
}
@@ -0,0 +1,27 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue4.ts] ////
=== narrowByClauseExpressionInSwitchTrue4.ts ===
declare const f: 'a' | 'b' | 'c';
>f : "a" | "b" | "c"
switch (true) {
>true : true
case f === "a":
>f === "a" : boolean
>f : "a" | "b" | "c"
>"a" : "a"
default:
f;
>f : "a" | "c"
case f === "b":
>f === "b" : boolean
>f : "a" | "b" | "c"
>"b" : "b"
f;
>f : "a" | "b" | "c"
}
@@ -0,0 +1,304 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue5.ts] ////
=== narrowByClauseExpressionInSwitchTrue5.ts ===
type A = { kind: "A", value: number };
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 0))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10))
>value : Symbol(value, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 21))
type B = { kind: "B", name: string };
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 38))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>name : Symbol(name, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 21))
type C = { kind: "C", cond: boolean };
>C : Symbol(C, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 37))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10))
>cond : Symbol(cond, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 21))
type D = { kind: "D", value: boolean };
>D : Symbol(D, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 38))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10))
>value : Symbol(value, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 21))
type E = { kind: "E", x: number, y: number };
>E : Symbol(E, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 39))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 21))
>y : Symbol(y, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 32))
type All = A | B | C | D | E;
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 0))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 38))
>C : Symbol(C, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 37))
>D : Symbol(D, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 38))
>E : Symbol(E, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 39))
function fn1switch(input: All) {
>fn1switch : Symbol(fn1switch, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 6, 29))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
switch (true) {
case input.kind === "A":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
case input.kind === "B":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
if (input.kind === "A") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
return;
}
input; // Should be B;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
// ^?
// fallthrough
case input.kind === "C":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
// ^?
break;
default:
input; // Should be D | E
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
// ^?
}
input; // Should not be A
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 8, 19))
// ^?
}
function fn1ifelse(input: All) {
>fn1ifelse : Symbol(fn1ifelse, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 31, 1))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
if (input.kind === "A" || input.kind === "B") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
if (input.kind === "A") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
return;
}
input; // Should be B;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
// ^?
}
if (input.kind === "C" || input.kind === "B") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
// ^?
}
else {
input; // Should be D | E
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
// ^?
}
input; // Should not be A
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 33, 19))
// ^?
}
function fn2switch(input: All) {
>fn2switch : Symbol(fn2switch, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 53, 1))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
switch (true) {
case input.kind === "A":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
case input.kind === "B":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
if (input.kind === "A") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
return;
}
input; // Should be B;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
// ^?
// fallthrough
case input.kind === "C":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
// ^?
break;
default:
input; // Should be D | E
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
// ^?
return;
}
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 55, 19))
// ^?
}
function fn2ifelse(input: All) {
>fn2ifelse : Symbol(fn2ifelse, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 79, 1))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
if (input.kind === "A" || input.kind === "B") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
if (input.kind === "A") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
return;
}
input; // Should be B;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
// ^?
}
if (input.kind === "C" || input.kind === "B") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
// ^?
}
else {
input; // Should be D | E
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
// ^?
return;
}
input; // Should be B | C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 81, 19))
// ^?
}
function fn3switch(input: All) {
>fn3switch : Symbol(fn3switch, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 102, 1))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
>All : Symbol(All, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 45))
switch (true) {
case input.kind === "A":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
case input.kind === "B":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
if (input.kind === "A") {
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10))
return;
}
input; // Should be B;
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
// ^?
// fallthrough
default:
input; // Should be B | D | E
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
// ^?
break;
case input.kind === "C":
>input.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 0, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 1, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 2, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 3, 10), Decl(narrowByClauseExpressionInSwitchTrue5.ts, 4, 10))
input; // Should be C
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
// ^?
break;
}
input; // Should not be A
>input : Symbol(input, Decl(narrowByClauseExpressionInSwitchTrue5.ts, 104, 19))
// ^?
}
@@ -0,0 +1,348 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue5.ts] ////
=== narrowByClauseExpressionInSwitchTrue5.ts ===
type A = { kind: "A", value: number };
>A : { kind: "A"; value: number; }
>kind : "A"
>value : number
type B = { kind: "B", name: string };
>B : { kind: "B"; name: string; }
>kind : "B"
>name : string
type C = { kind: "C", cond: boolean };
>C : { kind: "C"; cond: boolean; }
>kind : "C"
>cond : boolean
type D = { kind: "D", value: boolean };
>D : { kind: "D"; value: boolean; }
>kind : "D"
>value : boolean
type E = { kind: "E", x: number, y: number };
>E : { kind: "E"; x: number; y: number; }
>kind : "E"
>x : number
>y : number
type All = A | B | C | D | E;
>All : A | B | C | D | E
function fn1switch(input: All) {
>fn1switch : (input: All) => void
>input : All
switch (true) {
>true : true
case input.kind === "A":
>input.kind === "A" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"A" : "A"
case input.kind === "B":
>input.kind === "B" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"B" : "B"
if (input.kind === "A") {
>input.kind === "A" : boolean
>input.kind : "A" | "B"
>input : A | B
>kind : "A" | "B"
>"A" : "A"
return;
}
input; // Should be B;
>input : B
// ^?
// fallthrough
case input.kind === "C":
>input.kind === "C" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"C" : "C"
input; // Should be B | C
>input : B | C
// ^?
break;
default:
input; // Should be D | E
>input : D | E
// ^?
}
input; // Should not be A
>input : B | C | D | E
// ^?
}
function fn1ifelse(input: All) {
>fn1ifelse : (input: All) => void
>input : All
if (input.kind === "A" || input.kind === "B") {
>input.kind === "A" || input.kind === "B" : boolean
>input.kind === "A" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"A" : "A"
>input.kind === "B" : boolean
>input.kind : "B" | "C" | "D" | "E"
>input : B | C | D | E
>kind : "B" | "C" | "D" | "E"
>"B" : "B"
if (input.kind === "A") {
>input.kind === "A" : boolean
>input.kind : "A" | "B"
>input : A | B
>kind : "A" | "B"
>"A" : "A"
return;
}
input; // Should be B;
>input : B
// ^?
}
if (input.kind === "C" || input.kind === "B") {
>input.kind === "C" || input.kind === "B" : boolean
>input.kind === "C" : boolean
>input.kind : "B" | "C" | "D" | "E"
>input : B | C | D | E
>kind : "B" | "C" | "D" | "E"
>"C" : "C"
>input.kind === "B" : boolean
>input.kind : "B" | "D" | "E"
>input : B | D | E
>kind : "B" | "D" | "E"
>"B" : "B"
input; // Should be B | C
>input : B | C
// ^?
}
else {
input; // Should be D | E
>input : D | E
// ^?
}
input; // Should not be A
>input : B | C | D | E
// ^?
}
function fn2switch(input: All) {
>fn2switch : (input: All) => void
>input : All
switch (true) {
>true : true
case input.kind === "A":
>input.kind === "A" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"A" : "A"
case input.kind === "B":
>input.kind === "B" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"B" : "B"
if (input.kind === "A") {
>input.kind === "A" : boolean
>input.kind : "A" | "B"
>input : A | B
>kind : "A" | "B"
>"A" : "A"
return;
}
input; // Should be B;
>input : B
// ^?
// fallthrough
case input.kind === "C":
>input.kind === "C" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"C" : "C"
input; // Should be B | C
>input : B | C
// ^?
break;
default:
input; // Should be D | E
>input : D | E
// ^?
return;
}
input; // Should be B | C
>input : B | C
// ^?
}
function fn2ifelse(input: All) {
>fn2ifelse : (input: All) => void
>input : All
if (input.kind === "A" || input.kind === "B") {
>input.kind === "A" || input.kind === "B" : boolean
>input.kind === "A" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"A" : "A"
>input.kind === "B" : boolean
>input.kind : "B" | "C" | "D" | "E"
>input : B | C | D | E
>kind : "B" | "C" | "D" | "E"
>"B" : "B"
if (input.kind === "A") {
>input.kind === "A" : boolean
>input.kind : "A" | "B"
>input : A | B
>kind : "A" | "B"
>"A" : "A"
return;
}
input; // Should be B;
>input : B
// ^?
}
if (input.kind === "C" || input.kind === "B") {
>input.kind === "C" || input.kind === "B" : boolean
>input.kind === "C" : boolean
>input.kind : "B" | "C" | "D" | "E"
>input : B | C | D | E
>kind : "B" | "C" | "D" | "E"
>"C" : "C"
>input.kind === "B" : boolean
>input.kind : "B" | "D" | "E"
>input : B | D | E
>kind : "B" | "D" | "E"
>"B" : "B"
input; // Should be B | C
>input : B | C
// ^?
}
else {
input; // Should be D | E
>input : D | E
// ^?
return;
}
input; // Should be B | C
>input : B | C
// ^?
}
function fn3switch(input: All) {
>fn3switch : (input: All) => void
>input : All
switch (true) {
>true : true
case input.kind === "A":
>input.kind === "A" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"A" : "A"
case input.kind === "B":
>input.kind === "B" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"B" : "B"
if (input.kind === "A") {
>input.kind === "A" : boolean
>input.kind : "A" | "B"
>input : A | B
>kind : "A" | "B"
>"A" : "A"
return;
}
input; // Should be B;
>input : B
// ^?
// fallthrough
default:
input; // Should be B | D | E
>input : B | D | E
// ^?
break;
case input.kind === "C":
>input.kind === "C" : boolean
>input.kind : "A" | "B" | "C" | "D" | "E"
>input : All
>kind : "A" | "B" | "C" | "D" | "E"
>"C" : "C"
input; // Should be C
>input : C
// ^?
break;
}
input; // Should not be A
>input : B | C | D | E
// ^?
}
@@ -0,0 +1,89 @@
narrowByClauseExpressionInSwitchTrue6.ts(70,15): error TS2339: Property 'bProps' does not exist on type 'A | B'.
Property 'bProps' does not exist on type 'A'.
narrowByClauseExpressionInSwitchTrue6.ts(73,15): error TS2339: Property 'cProps' does not exist on type 'MyType'.
Property 'cProps' does not exist on type 'A'.
==== narrowByClauseExpressionInSwitchTrue6.ts (2 errors) ====
interface A {
kind: "a";
aProps: string;
}
interface B {
kind: "b";
bProps: string;
}
interface C {
kind: "c";
cProps: string;
}
type MyType = A | B | C;
function isA(x: MyType) {
switch (true) {
default:
const never: never = x;
case x.kind === "a":
x.aProps;
break;
case x.kind === "b":
x.bProps;
break;
case x.kind === "c":
x.cProps;
break;
}
switch (true) {
default:
const never: never = x;
case x.kind === "a": {
x.aProps;
break;
}
case x.kind === "b": {
x.bProps;
break;
}
case x.kind === "c": {
x.cProps;
break;
}
}
switch (true) {
default:
x.aProps;
break;
case x.kind === "b":
x.bProps;
break;
case x.kind === "c":
x.cProps;
break;
}
switch (true) {
default:
const never: never = x;
case x.kind === "a":
x.aProps;
// fallthrough
case x.kind === "b":
x.bProps;
~~~~~~
!!! error TS2339: Property 'bProps' does not exist on type 'A | B'.
!!! error TS2339: Property 'bProps' does not exist on type 'A'.
// fallthrough
case x.kind === "c":
x.cProps;
~~~~~~
!!! error TS2339: Property 'cProps' does not exist on type 'MyType'.
!!! error TS2339: Property 'cProps' does not exist on type 'A'.
}
}
@@ -0,0 +1,198 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue6.ts] ////
=== narrowByClauseExpressionInSwitchTrue6.ts ===
interface A {
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 0))
kind: "a";
>kind : Symbol(A.kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13))
aProps: string;
>aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
}
interface B {
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 3, 1))
kind: "b";
>kind : Symbol(B.kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13))
bProps: string;
>bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
}
interface C {
>C : Symbol(C, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 8, 1))
kind: "c";
>kind : Symbol(C.kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
cProps: string;
>cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
}
type MyType = A | B | C;
>MyType : Symbol(MyType, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 13, 1))
>A : Symbol(A, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 0))
>B : Symbol(B, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 3, 1))
>C : Symbol(C, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 8, 1))
function isA(x: MyType) {
>isA : Symbol(isA, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 16, 24))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>MyType : Symbol(MyType, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 13, 1))
switch (true) {
default:
const never: never = x;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 21, 17))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
case x.kind === "a":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.aProps;
>x.aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
break;
case x.kind === "b":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.bProps;
>x.bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
break;
case x.kind === "c":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.cProps;
>x.cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
break;
}
switch (true) {
default:
const never: never = x;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 35, 17))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
case x.kind === "a": {
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.aProps;
>x.aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
break;
}
case x.kind === "b": {
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.bProps;
>x.bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
break;
}
case x.kind === "c": {
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.cProps;
>x.cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
break;
}
}
switch (true) {
default:
x.aProps;
>x.aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
break;
case x.kind === "b":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.bProps;
>x.bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>bProps : Symbol(B.bProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 6, 14))
break;
case x.kind === "c":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.cProps;
>x.cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>cProps : Symbol(C.cProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 11, 14))
break;
}
switch (true) {
default:
const never: never = x;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 64, 17))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
case x.kind === "a":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.aProps;
>x.aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>aProps : Symbol(A.aProps, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 1, 14))
// fallthrough
case x.kind === "b":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.bProps;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
// fallthrough
case x.kind === "c":
>x.kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
>kind : Symbol(kind, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 0, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 5, 13), Decl(narrowByClauseExpressionInSwitchTrue6.ts, 10, 13))
x.cProps;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue6.ts, 18, 13))
}
}
@@ -0,0 +1,222 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue6.ts] ////
=== narrowByClauseExpressionInSwitchTrue6.ts ===
interface A {
kind: "a";
>kind : "a"
aProps: string;
>aProps : string
}
interface B {
kind: "b";
>kind : "b"
bProps: string;
>bProps : string
}
interface C {
kind: "c";
>kind : "c"
cProps: string;
>cProps : string
}
type MyType = A | B | C;
>MyType : A | B | C
function isA(x: MyType) {
>isA : (x: MyType) => void
>x : MyType
switch (true) {
>true : true
default:
const never: never = x;
>never : never
>x : never
case x.kind === "a":
>x.kind === "a" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"a" : "a"
x.aProps;
>x.aProps : string
>x : A
>aProps : string
break;
case x.kind === "b":
>x.kind === "b" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"b" : "b"
x.bProps;
>x.bProps : string
>x : B
>bProps : string
break;
case x.kind === "c":
>x.kind === "c" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"c" : "c"
x.cProps;
>x.cProps : string
>x : C
>cProps : string
break;
}
switch (true) {
>true : true
default:
const never: never = x;
>never : never
>x : never
case x.kind === "a": {
>x.kind === "a" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"a" : "a"
x.aProps;
>x.aProps : string
>x : A
>aProps : string
break;
}
case x.kind === "b": {
>x.kind === "b" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"b" : "b"
x.bProps;
>x.bProps : string
>x : B
>bProps : string
break;
}
case x.kind === "c": {
>x.kind === "c" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"c" : "c"
x.cProps;
>x.cProps : string
>x : C
>cProps : string
break;
}
}
switch (true) {
>true : true
default:
x.aProps;
>x.aProps : string
>x : A
>aProps : string
break;
case x.kind === "b":
>x.kind === "b" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"b" : "b"
x.bProps;
>x.bProps : string
>x : B
>bProps : string
break;
case x.kind === "c":
>x.kind === "c" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"c" : "c"
x.cProps;
>x.cProps : string
>x : C
>cProps : string
break;
}
switch (true) {
>true : true
default:
const never: never = x;
>never : never
>x : never
case x.kind === "a":
>x.kind === "a" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"a" : "a"
x.aProps;
>x.aProps : string
>x : A
>aProps : string
// fallthrough
case x.kind === "b":
>x.kind === "b" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"b" : "b"
x.bProps;
>x.bProps : any
>x : A | B
>bProps : any
// fallthrough
case x.kind === "c":
>x.kind === "c" : boolean
>x.kind : "a" | "b" | "c"
>x : MyType
>kind : "a" | "b" | "c"
>"c" : "c"
x.cProps;
>x.cProps : any
>x : MyType
>cProps : any
}
}
@@ -0,0 +1,90 @@
narrowByClauseExpressionInSwitchTrue7.ts(80,19): error TS2322: Type 'Derived2' is not assignable to type 'never'.
==== narrowByClauseExpressionInSwitchTrue7.ts (1 errors) ====
class Base {
basey: string = "";
}
class Derived1 extends Base {
d: string = "";
}
class Derived2 extends Base {
d: string = "";
other: string = "";
}
function classy(base: Base, someDerived: Derived1 | Derived2) {
switch (true) {
case base instanceof Derived1:
base.d
// fallthrough
default:
base.basey
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d
break;
case someDerived instanceof Derived2:
someDerived.d
break
default:
const never: never = someDerived;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d
// fallthrough
case someDerived instanceof Derived2:
someDerived.d
break
default:
const never: never = someDerived;
}
switch (true) {
default:
const never: never = someDerived;
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
default:
const never: never = someDerived;
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
default:
someDerived.d;
someDerived.other;
const never: never = someDerived;
~~~~~
!!! error TS2322: Type 'Derived2' is not assignable to type 'never'.
}
}
@@ -0,0 +1,229 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue7.ts] ////
=== narrowByClauseExpressionInSwitchTrue7.ts ===
class Base {
>Base : Symbol(Base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 0))
basey: string = "";
>basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
}
class Derived1 extends Base {
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
>Base : Symbol(Base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 0))
d: string = "";
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
}
class Derived2 extends Base {
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
>Base : Symbol(Base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 0))
d: string = "";
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
other: string = "";
>other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
}
function classy(base: Base, someDerived: Derived1 | Derived2) {
>classy : Symbol(classy, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 11, 1))
>base : Symbol(base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 16))
>Base : Symbol(Base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 0))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
switch (true) {
case base instanceof Derived1:
>base : Symbol(base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 16))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
base.d
>base.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>base : Symbol(base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 16))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
// fallthrough
default:
base.basey
>base.basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
>base : Symbol(base, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 16))
>basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
}
switch (true) {
case someDerived instanceof Derived1:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
someDerived.d
>someDerived.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
break;
case someDerived instanceof Derived2:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
someDerived.d
>someDerived.d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
break
default:
const never: never = someDerived;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 30, 17))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
}
switch (true) {
case someDerived instanceof Derived1:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
someDerived.d
>someDerived.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
// fallthrough
case someDerived instanceof Derived2:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
someDerived.d
>someDerived.d : Symbol(d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29), Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29), Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
break
default:
const never: never = someDerived;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 41, 17))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
}
switch (true) {
default:
const never: never = someDerived;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 46, 17))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
case someDerived instanceof Derived1:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
someDerived.d;
>someDerived.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
someDerived.basey;
>someDerived.basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
break
case someDerived instanceof Derived2:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
someDerived.d;
>someDerived.d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
someDerived.other;
>someDerived.other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
}
switch (true) {
case someDerived instanceof Derived1:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
someDerived.d;
>someDerived.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
someDerived.basey;
>someDerived.basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
break
default:
const never: never = someDerived;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 62, 17))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
case someDerived instanceof Derived2:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
someDerived.d;
>someDerived.d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
someDerived.other;
>someDerived.other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
}
switch (true) {
case someDerived instanceof Derived1:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived1 : Symbol(Derived1, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 2, 1))
someDerived.d;
>someDerived.d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived1.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 4, 29))
someDerived.basey;
>someDerived.basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>basey : Symbol(Base.basey, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 0, 12))
break
case someDerived instanceof Derived2:
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>Derived2 : Symbol(Derived2, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 6, 1))
someDerived.d;
>someDerived.d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
someDerived.other;
>someDerived.other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
default:
someDerived.d;
>someDerived.d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>d : Symbol(Derived2.d, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 8, 29))
someDerived.other;
>someDerived.other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
>other : Symbol(Derived2.other, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 9, 19))
const never: never = someDerived;
>never : Symbol(never, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 79, 17))
>someDerived : Symbol(someDerived, Decl(narrowByClauseExpressionInSwitchTrue7.ts, 13, 27))
}
}
@@ -0,0 +1,253 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue7.ts] ////
=== narrowByClauseExpressionInSwitchTrue7.ts ===
class Base {
>Base : Base
basey: string = "";
>basey : string
>"" : ""
}
class Derived1 extends Base {
>Derived1 : Derived1
>Base : Base
d: string = "";
>d : string
>"" : ""
}
class Derived2 extends Base {
>Derived2 : Derived2
>Base : Base
d: string = "";
>d : string
>"" : ""
other: string = "";
>other : string
>"" : ""
}
function classy(base: Base, someDerived: Derived1 | Derived2) {
>classy : (base: Base, someDerived: Derived1 | Derived2) => void
>base : Base
>someDerived : Derived1 | Derived2
switch (true) {
>true : true
case base instanceof Derived1:
>base instanceof Derived1 : boolean
>base : Base
>Derived1 : typeof Derived1
base.d
>base.d : string
>base : Derived1
>d : string
// fallthrough
default:
base.basey
>base.basey : string
>base : Base
>basey : string
}
switch (true) {
>true : true
case someDerived instanceof Derived1:
>someDerived instanceof Derived1 : boolean
>someDerived : Derived1 | Derived2
>Derived1 : typeof Derived1
someDerived.d
>someDerived.d : string
>someDerived : Derived1
>d : string
break;
case someDerived instanceof Derived2:
>someDerived instanceof Derived2 : boolean
>someDerived : Derived1 | Derived2
>Derived2 : typeof Derived2
someDerived.d
>someDerived.d : string
>someDerived : Derived2
>d : string
break
default:
const never: never = someDerived;
>never : never
>someDerived : never
}
switch (true) {
>true : true
case someDerived instanceof Derived1:
>someDerived instanceof Derived1 : boolean
>someDerived : Derived1 | Derived2
>Derived1 : typeof Derived1
someDerived.d
>someDerived.d : string
>someDerived : Derived1
>d : string
// fallthrough
case someDerived instanceof Derived2:
>someDerived instanceof Derived2 : boolean
>someDerived : Derived1 | Derived2
>Derived2 : typeof Derived2
someDerived.d
>someDerived.d : string
>someDerived : Derived1 | Derived2
>d : string
break
default:
const never: never = someDerived;
>never : never
>someDerived : never
}
switch (true) {
>true : true
default:
const never: never = someDerived;
>never : never
>someDerived : never
case someDerived instanceof Derived1:
>someDerived instanceof Derived1 : boolean
>someDerived : Derived1 | Derived2
>Derived1 : typeof Derived1
someDerived.d;
>someDerived.d : string
>someDerived : Derived1
>d : string
someDerived.basey;
>someDerived.basey : string
>someDerived : Derived1
>basey : string
break
case someDerived instanceof Derived2:
>someDerived instanceof Derived2 : boolean
>someDerived : Derived1 | Derived2
>Derived2 : typeof Derived2
someDerived.d;
>someDerived.d : string
>someDerived : Derived2
>d : string
someDerived.other;
>someDerived.other : string
>someDerived : Derived2
>other : string
}
switch (true) {
>true : true
case someDerived instanceof Derived1:
>someDerived instanceof Derived1 : boolean
>someDerived : Derived1 | Derived2
>Derived1 : typeof Derived1
someDerived.d;
>someDerived.d : string
>someDerived : Derived1
>d : string
someDerived.basey;
>someDerived.basey : string
>someDerived : Derived1
>basey : string
break
default:
const never: never = someDerived;
>never : never
>someDerived : never
case someDerived instanceof Derived2:
>someDerived instanceof Derived2 : boolean
>someDerived : Derived1 | Derived2
>Derived2 : typeof Derived2
someDerived.d;
>someDerived.d : string
>someDerived : Derived2
>d : string
someDerived.other;
>someDerived.other : string
>someDerived : Derived2
>other : string
}
switch (true) {
>true : true
case someDerived instanceof Derived1:
>someDerived instanceof Derived1 : boolean
>someDerived : Derived1 | Derived2
>Derived1 : typeof Derived1
someDerived.d;
>someDerived.d : string
>someDerived : Derived1
>d : string
someDerived.basey;
>someDerived.basey : string
>someDerived : Derived1
>basey : string
break
case someDerived instanceof Derived2:
>someDerived instanceof Derived2 : boolean
>someDerived : Derived1 | Derived2
>Derived2 : typeof Derived2
someDerived.d;
>someDerived.d : string
>someDerived : Derived2
>d : string
someDerived.other;
>someDerived.other : string
>someDerived : Derived2
>other : string
default:
someDerived.d;
>someDerived.d : string
>someDerived : Derived2
>d : string
someDerived.other;
>someDerived.other : string
>someDerived : Derived2
>other : string
const never: never = someDerived;
>never : never
>someDerived : Derived2
}
}
@@ -0,0 +1,57 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue8.ts] ////
=== narrowByClauseExpressionInSwitchTrue8.ts ===
function foo(cond1: boolean, cond2: boolean) {
>foo : Symbol(foo, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 0))
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
switch (true) {
case cond1:
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
cond1; // Should be true
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
// ^?
cond2; // Should be boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
// ^?
break;
case cond2:
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
cond1; // Should be false?
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
// ^?
cond2; // Should be true
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
// ^?
break;
default:
cond1; // Should be false?
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
// ^?
cond2; // Should be false?
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
// ^?
break;
}
cond1; // Should be boolean
>cond1 : Symbol(cond1, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 13))
// ^?
cond2; // Should be boolean
>cond2 : Symbol(cond2, Decl(narrowByClauseExpressionInSwitchTrue8.ts, 0, 28))
// ^?
}
@@ -0,0 +1,59 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue8.ts] ////
=== narrowByClauseExpressionInSwitchTrue8.ts ===
function foo(cond1: boolean, cond2: boolean) {
>foo : (cond1: boolean, cond2: boolean) => void
>cond1 : boolean
>cond2 : boolean
switch (true) {
>true : true
case cond1:
>cond1 : boolean
cond1; // Should be true
>cond1 : true
// ^?
cond2; // Should be boolean
>cond2 : boolean
// ^?
break;
case cond2:
>cond2 : boolean
cond1; // Should be false?
>cond1 : false
// ^?
cond2; // Should be true
>cond2 : true
// ^?
break;
default:
cond1; // Should be false?
>cond1 : false
// ^?
cond2; // Should be false?
>cond2 : false
// ^?
break;
}
cond1; // Should be boolean
>cond1 : boolean
// ^?
cond2; // Should be boolean
>cond2 : boolean
// ^?
}
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue9.ts] ////
=== narrowByClauseExpressionInSwitchTrue9.ts ===
interface IProps {
>IProps : Symbol(IProps, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 0, 0))
one: boolean;
>one : Symbol(IProps.one, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 0, 18))
}
class Foo {
>Foo : Symbol(Foo, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 2, 1))
mine: string = "";
>mine : Symbol(Foo.mine, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 4, 11))
myMethod(x: IProps) {
>myMethod : Symbol(Foo.myMethod, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 5, 22))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 7, 13))
>IProps : Symbol(IProps, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 0, 0))
const { one } = x;
>one : Symbol(one, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 8, 15))
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 7, 13))
switch (true) {
case one:
>one : Symbol(one, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 8, 15))
break;
default:
let x = this.mine;
>x : Symbol(x, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 13, 19))
>this.mine : Symbol(Foo.mine, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 4, 11))
>this : Symbol(Foo, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 2, 1))
>mine : Symbol(Foo.mine, Decl(narrowByClauseExpressionInSwitchTrue9.ts, 4, 11))
}
}
}
@@ -0,0 +1,40 @@
//// [tests/cases/compiler/narrowByClauseExpressionInSwitchTrue9.ts] ////
=== narrowByClauseExpressionInSwitchTrue9.ts ===
interface IProps {
one: boolean;
>one : boolean
}
class Foo {
>Foo : Foo
mine: string = "";
>mine : string
>"" : ""
myMethod(x: IProps) {
>myMethod : (x: IProps) => void
>x : IProps
const { one } = x;
>one : boolean
>x : IProps
switch (true) {
>true : true
case one:
>one : boolean
break;
default:
let x = this.mine;
>x : string
>this.mine : string
>this : this
>mine : string
}
}
}
@@ -0,0 +1,56 @@
// @strict: true
// @noEmit: true
function foo(cond1: boolean, cond2: boolean) {
switch (true) {
case cond1 || cond2:
cond1; // boolean
// ^?
cond2; // boolean
// ^?
break;
case cond2:
cond1; // false
// ^?
cond2;; // never
// ^?
break;
default:
cond1; // false
// ^?
cond2; // false
// ^?
break;
}
cond1; // boolean
// ^?
cond2; // boolean
// ^?
}
function blah(cond1: boolean, cond2: boolean) {
if (cond1 || cond2) {
cond1; // boolean
// ^?
cond2; // boolean
// ^?
} else if (cond2) {
cond1; // false
// ^?
cond2; // never
// ^?
} else {
cond1; // false
// ^?
cond2; // false
// ^?
}
cond1; // boolean
// ^?
cond2; // boolean
// ^?
}
@@ -0,0 +1,29 @@
// @strict: true
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/55986
declare const f: 'a' | 'b' | 'c';
switch(true) {
case f === 'a':
case f === 'b':
f;
break
default:
f;
}
f;
switch(true) {
case f === 'a':
f;
case f === 'b':
f;
break
default:
f;
}
f;
@@ -0,0 +1,22 @@
// @strict: true
// @noEmit: true
type Shape =
| { kind: "circle", radius: number }
| { kind: "square", sideLength: number }
function wat(shape: Shape) {
switch (true) {
case shape.kind === "circle":
return Math.PI * shape.radius ** 2;
case shape.kind === "circle": // should error
}
if (shape.kind === "circle") {
return Math.PI * shape.radius ** 2;
}
else if (shape.kind === "circle") {
// ~~~~
// Property 'kind' does not exist on type 'never'.
}
}
@@ -0,0 +1,12 @@
// @strict: true
// @noEmit: true
declare const f: 'a' | 'b' | 'c';
switch (true) {
case f === "a":
default:
f;
case f === "b":
f;
}
@@ -0,0 +1,133 @@
// @strict: true
// @noEmit: true
type A = { kind: "A", value: number };
type B = { kind: "B", name: string };
type C = { kind: "C", cond: boolean };
type D = { kind: "D", value: boolean };
type E = { kind: "E", x: number, y: number };
type All = A | B | C | D | E;
function fn1switch(input: All) {
switch (true) {
case input.kind === "A":
case input.kind === "B":
if (input.kind === "A") {
return;
}
input; // Should be B;
// ^?
// fallthrough
case input.kind === "C":
input; // Should be B | C
// ^?
break;
default:
input; // Should be D | E
// ^?
}
input; // Should not be A
// ^?
}
function fn1ifelse(input: All) {
if (input.kind === "A" || input.kind === "B") {
if (input.kind === "A") {
return;
}
input; // Should be B;
// ^?
}
if (input.kind === "C" || input.kind === "B") {
input; // Should be B | C
// ^?
}
else {
input; // Should be D | E
// ^?
}
input; // Should not be A
// ^?
}
function fn2switch(input: All) {
switch (true) {
case input.kind === "A":
case input.kind === "B":
if (input.kind === "A") {
return;
}
input; // Should be B;
// ^?
// fallthrough
case input.kind === "C":
input; // Should be B | C
// ^?
break;
default:
input; // Should be D | E
// ^?
return;
}
input; // Should be B | C
// ^?
}
function fn2ifelse(input: All) {
if (input.kind === "A" || input.kind === "B") {
if (input.kind === "A") {
return;
}
input; // Should be B;
// ^?
}
if (input.kind === "C" || input.kind === "B") {
input; // Should be B | C
// ^?
}
else {
input; // Should be D | E
// ^?
return;
}
input; // Should be B | C
// ^?
}
function fn3switch(input: All) {
switch (true) {
case input.kind === "A":
case input.kind === "B":
if (input.kind === "A") {
return;
}
input; // Should be B;
// ^?
// fallthrough
default:
input; // Should be B | D | E
// ^?
break;
case input.kind === "C":
input; // Should be C
// ^?
break;
}
input; // Should not be A
// ^?
}
@@ -0,0 +1,78 @@
// @strict: true
// @noEmit: true
interface A {
kind: "a";
aProps: string;
}
interface B {
kind: "b";
bProps: string;
}
interface C {
kind: "c";
cProps: string;
}
type MyType = A | B | C;
function isA(x: MyType) {
switch (true) {
default:
const never: never = x;
case x.kind === "a":
x.aProps;
break;
case x.kind === "b":
x.bProps;
break;
case x.kind === "c":
x.cProps;
break;
}
switch (true) {
default:
const never: never = x;
case x.kind === "a": {
x.aProps;
break;
}
case x.kind === "b": {
x.bProps;
break;
}
case x.kind === "c": {
x.cProps;
break;
}
}
switch (true) {
default:
x.aProps;
break;
case x.kind === "b":
x.bProps;
break;
case x.kind === "c":
x.cProps;
break;
}
switch (true) {
default:
const never: never = x;
case x.kind === "a":
x.aProps;
// fallthrough
case x.kind === "b":
x.bProps;
// fallthrough
case x.kind === "c":
x.cProps;
}
}
@@ -0,0 +1,86 @@
// @strict: true
// @noEmit: true
class Base {
basey: string = "";
}
class Derived1 extends Base {
d: string = "";
}
class Derived2 extends Base {
d: string = "";
other: string = "";
}
function classy(base: Base, someDerived: Derived1 | Derived2) {
switch (true) {
case base instanceof Derived1:
base.d
// fallthrough
default:
base.basey
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d
break;
case someDerived instanceof Derived2:
someDerived.d
break
default:
const never: never = someDerived;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d
// fallthrough
case someDerived instanceof Derived2:
someDerived.d
break
default:
const never: never = someDerived;
}
switch (true) {
default:
const never: never = someDerived;
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
default:
const never: never = someDerived;
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
}
switch (true) {
case someDerived instanceof Derived1:
someDerived.d;
someDerived.basey;
break
case someDerived instanceof Derived2:
someDerived.d;
someDerived.other;
default:
someDerived.d;
someDerived.other;
const never: never = someDerived;
}
}
@@ -0,0 +1,32 @@
// @strict: true
// @noEmit: true
function foo(cond1: boolean, cond2: boolean) {
switch (true) {
case cond1:
cond1; // Should be true
// ^?
cond2; // Should be boolean
// ^?
break;
case cond2:
cond1; // Should be false?
// ^?
cond2; // Should be true
// ^?
break;
default:
cond1; // Should be false?
// ^?
cond2; // Should be false?
// ^?
break;
}
cond1; // Should be boolean
// ^?
cond2; // Should be boolean
// ^?
}
@@ -0,0 +1,20 @@
// @strict: true
// @noEmit: true
interface IProps {
one: boolean;
}
class Foo {
mine: string = "";
myMethod(x: IProps) {
const { one } = x;
switch (true) {
case one:
break;
default:
let x = this.mine;
}
}
}