diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ec5d1961f1a1c..bcaa21d9469af 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27424,11 +27424,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) { @@ -28043,6 +28039,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") && diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.symbols deleted file mode 100644 index 6461b7c88b263..0000000000000 --- a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.symbols +++ /dev/null @@ -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; - } -} - diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.symbols new file mode 100644 index 0000000000000..3892a6c7fddf4 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.symbols @@ -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; + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.types similarity index 90% rename from tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.types rename to tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.types index f8a1d9bc87e42..fa20aae9246ba 100644 --- a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue.types +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue1.types @@ -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" }; diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.symbols new file mode 100644 index 0000000000000..2abb5fc5d41ec --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.symbols @@ -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)) + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.types new file mode 100644 index 0000000000000..d6e8cedfdc64e --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue10.types @@ -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 + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.symbols new file mode 100644 index 0000000000000..8ce5e2928f487 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.symbols @@ -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)) + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.types new file mode 100644 index 0000000000000..d1637eb248fd5 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue2.types @@ -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" + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.errors.txt b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.errors.txt new file mode 100644 index 0000000000000..cec1802a21fcf --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.errors.txt @@ -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'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.symbols new file mode 100644 index 0000000000000..b6811492524e1 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.symbols @@ -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'. + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.types new file mode 100644 index 0000000000000..1fde85a02984d --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue3.types @@ -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'. + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.symbols new file mode 100644 index 0000000000000..c505b1d47c975 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.symbols @@ -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)) +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.types new file mode 100644 index 0000000000000..8dc6062a2b695 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue4.types @@ -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" +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.symbols new file mode 100644 index 0000000000000..3c890662516f5 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.symbols @@ -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)) + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.types new file mode 100644 index 0000000000000..d2b4c5c0780de --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue5.types @@ -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 + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.errors.txt b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.errors.txt new file mode 100644 index 0000000000000..e33e6ac6fceab --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.errors.txt @@ -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'. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.symbols new file mode 100644 index 0000000000000..9ed6be6a7cf6c --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.symbols @@ -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)) + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.types new file mode 100644 index 0000000000000..4a96c67b07136 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue6.types @@ -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 + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.errors.txt b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.errors.txt new file mode 100644 index 0000000000000..ae09d39b7ca88 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.errors.txt @@ -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'. + } + + } + \ No newline at end of file diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.symbols new file mode 100644 index 0000000000000..ad0dd8f89d894 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.symbols @@ -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)) + } + +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.types new file mode 100644 index 0000000000000..a783c583b22f3 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue7.types @@ -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 + } + +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.symbols new file mode 100644 index 0000000000000..ec14234e62b6c --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.symbols @@ -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)) + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.types new file mode 100644 index 0000000000000..45230dc5e12b9 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue8.types @@ -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 + + // ^? +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.symbols b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.symbols new file mode 100644 index 0000000000000..1cbdfc55b276d --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.symbols @@ -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)) + } + } +} + diff --git a/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.types b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.types new file mode 100644 index 0000000000000..75557462a5b20 --- /dev/null +++ b/tests/baselines/reference/narrowByClauseExpressionInSwitchTrue9.types @@ -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 + } + } +} + diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue1.ts similarity index 100% rename from tests/cases/compiler/narrowByClauseExpressionInSwitchTrue.ts rename to tests/cases/compiler/narrowByClauseExpressionInSwitchTrue1.ts diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue10.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue10.ts new file mode 100644 index 0000000000000..7d48369ca34e0 --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue10.ts @@ -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 + // ^? +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue2.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue2.ts new file mode 100644 index 0000000000000..461e3505c393a --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue2.ts @@ -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; diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue3.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue3.ts new file mode 100644 index 0000000000000..d0dbafccbb108 --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue3.ts @@ -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'. + } +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue4.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue4.ts new file mode 100644 index 0000000000000..15596fd7ad11a --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue4.ts @@ -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; +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue5.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue5.ts new file mode 100644 index 0000000000000..f4aee3ff151e1 --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue5.ts @@ -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 + // ^? +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue6.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue6.ts new file mode 100644 index 0000000000000..491355b79e906 --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue6.ts @@ -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; + } +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue7.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue7.ts new file mode 100644 index 0000000000000..d482d8fa033a4 --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue7.ts @@ -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; + } + +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue8.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue8.ts new file mode 100644 index 0000000000000..3572817cba99b --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue8.ts @@ -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 + // ^? +} diff --git a/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue9.ts b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue9.ts new file mode 100644 index 0000000000000..1f8942d90b1fb --- /dev/null +++ b/tests/cases/compiler/narrowByClauseExpressionInSwitchTrue9.ts @@ -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; + } + } +}