diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2c9344679abd8..4c31ece8602d0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27446,7 +27446,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType { - const expr = flow.switchStatement.expression; + const expr = skipParentheses(flow.switchStatement.expression); const flowType = getTypeAtFlowNode(flow.antecedent); let type = getTypeFromFlowType(flowType); if (isMatchingReference(reference, expr)) { diff --git a/tests/baselines/reference/narrowByParenthesizedSwitchExpression.symbols b/tests/baselines/reference/narrowByParenthesizedSwitchExpression.symbols new file mode 100644 index 0000000000000..4bcf3c49d1644 --- /dev/null +++ b/tests/baselines/reference/narrowByParenthesizedSwitchExpression.symbols @@ -0,0 +1,66 @@ +//// [tests/cases/compiler/narrowByParenthesizedSwitchExpression.ts] //// + +=== narrowByParenthesizedSwitchExpression.ts === +interface Base { +>Base : Symbol(Base, Decl(narrowByParenthesizedSwitchExpression.ts, 0, 0)) + + type: "foo" | "bar"; +>type : Symbol(Base.type, Decl(narrowByParenthesizedSwitchExpression.ts, 0, 16)) +} + +interface Foo extends Base { +>Foo : Symbol(Foo, Decl(narrowByParenthesizedSwitchExpression.ts, 2, 1)) +>Base : Symbol(Base, Decl(narrowByParenthesizedSwitchExpression.ts, 0, 0)) + + type: "foo"; +>type : Symbol(Foo.type, Decl(narrowByParenthesizedSwitchExpression.ts, 4, 28)) + + foo: string; +>foo : Symbol(Foo.foo, Decl(narrowByParenthesizedSwitchExpression.ts, 5, 14)) +} + +interface Bar extends Base { +>Bar : Symbol(Bar, Decl(narrowByParenthesizedSwitchExpression.ts, 7, 1)) +>Base : Symbol(Base, Decl(narrowByParenthesizedSwitchExpression.ts, 0, 0)) + + type: "bar"; +>type : Symbol(Bar.type, Decl(narrowByParenthesizedSwitchExpression.ts, 9, 28)) + + bar: number; +>bar : Symbol(Bar.bar, Decl(narrowByParenthesizedSwitchExpression.ts, 10, 14)) +} + +function getV(): Foo | Bar { +>getV : Symbol(getV, Decl(narrowByParenthesizedSwitchExpression.ts, 12, 1)) +>Foo : Symbol(Foo, Decl(narrowByParenthesizedSwitchExpression.ts, 2, 1)) +>Bar : Symbol(Bar, Decl(narrowByParenthesizedSwitchExpression.ts, 7, 1)) + + return null!; +} + +const v = getV(); +>v : Symbol(v, Decl(narrowByParenthesizedSwitchExpression.ts, 18, 5)) +>getV : Symbol(getV, Decl(narrowByParenthesizedSwitchExpression.ts, 12, 1)) + +switch ((v.type)) { +>v.type : Symbol(type, Decl(narrowByParenthesizedSwitchExpression.ts, 4, 28), Decl(narrowByParenthesizedSwitchExpression.ts, 9, 28)) +>v : Symbol(v, Decl(narrowByParenthesizedSwitchExpression.ts, 18, 5)) +>type : Symbol(type, Decl(narrowByParenthesizedSwitchExpression.ts, 4, 28), Decl(narrowByParenthesizedSwitchExpression.ts, 9, 28)) + + case "bar": + v.bar; +>v.bar : Symbol(Bar.bar, Decl(narrowByParenthesizedSwitchExpression.ts, 10, 14)) +>v : Symbol(v, Decl(narrowByParenthesizedSwitchExpression.ts, 18, 5)) +>bar : Symbol(Bar.bar, Decl(narrowByParenthesizedSwitchExpression.ts, 10, 14)) + + break; + + case "foo": + v.foo; +>v.foo : Symbol(Foo.foo, Decl(narrowByParenthesizedSwitchExpression.ts, 5, 14)) +>v : Symbol(v, Decl(narrowByParenthesizedSwitchExpression.ts, 18, 5)) +>foo : Symbol(Foo.foo, Decl(narrowByParenthesizedSwitchExpression.ts, 5, 14)) + + break; +} + diff --git a/tests/baselines/reference/narrowByParenthesizedSwitchExpression.types b/tests/baselines/reference/narrowByParenthesizedSwitchExpression.types new file mode 100644 index 0000000000000..6601417a33c13 --- /dev/null +++ b/tests/baselines/reference/narrowByParenthesizedSwitchExpression.types @@ -0,0 +1,63 @@ +//// [tests/cases/compiler/narrowByParenthesizedSwitchExpression.ts] //// + +=== narrowByParenthesizedSwitchExpression.ts === +interface Base { + type: "foo" | "bar"; +>type : "foo" | "bar" +} + +interface Foo extends Base { + type: "foo"; +>type : "foo" + + foo: string; +>foo : string +} + +interface Bar extends Base { + type: "bar"; +>type : "bar" + + bar: number; +>bar : number +} + +function getV(): Foo | Bar { +>getV : () => Foo | Bar + + return null!; +>null! : never +} + +const v = getV(); +>v : Foo | Bar +>getV() : Foo | Bar +>getV : () => Foo | Bar + +switch ((v.type)) { +>(v.type) : "foo" | "bar" +>v.type : "foo" | "bar" +>v : Foo | Bar +>type : "foo" | "bar" + + case "bar": +>"bar" : "bar" + + v.bar; +>v.bar : number +>v : Bar +>bar : number + + break; + + case "foo": +>"foo" : "foo" + + v.foo; +>v.foo : string +>v : Foo +>foo : string + + break; +} + diff --git a/tests/cases/compiler/narrowByParenthesizedSwitchExpression.ts b/tests/cases/compiler/narrowByParenthesizedSwitchExpression.ts new file mode 100644 index 0000000000000..2f2d9330ce1d8 --- /dev/null +++ b/tests/cases/compiler/narrowByParenthesizedSwitchExpression.ts @@ -0,0 +1,32 @@ +// @strict: true +// @noEmit: true + +interface Base { + type: "foo" | "bar"; +} + +interface Foo extends Base { + type: "foo"; + foo: string; +} + +interface Bar extends Base { + type: "bar"; + bar: number; +} + +function getV(): Foo | Bar { + return null!; +} + +const v = getV(); + +switch ((v.type)) { + case "bar": + v.bar; + break; + + case "foo": + v.foo; + break; +}