Skip to content

Commit bc8ac16

Browse files
authored
Port "Check if switch statements are exhaustive when their expressions is generic with a literal type constraint" (#1071)
1 parent 9ca67e4 commit bc8ac16

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

internal/checker/flow.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,7 @@ func (c *Checker) computeExhaustiveSwitchStatement(node *ast.Node) bool {
19291929
return c.getTypeFacts(t, notEqualFacts) == notEqualFacts
19301930
})
19311931
}
1932-
t := c.checkExpressionCached(node.Expression())
1932+
t := c.getBaseConstraintOrType(c.checkExpressionCached(node.Expression()))
19331933
if !isLiteralType(t) {
19341934
return false
19351935
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//// [tests/cases/compiler/exhaustiveSwitchStatementsGeneric1.ts] ////
2+
3+
=== exhaustiveSwitchStatementsGeneric1.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/986
5+
6+
interface A {
7+
>A : Symbol(A, Decl(exhaustiveSwitchStatementsGeneric1.ts, 0, 0))
8+
9+
type: "a";
10+
>type : Symbol(type, Decl(exhaustiveSwitchStatementsGeneric1.ts, 2, 13))
11+
}
12+
13+
interface B {
14+
>B : Symbol(B, Decl(exhaustiveSwitchStatementsGeneric1.ts, 4, 1))
15+
16+
type: "b";
17+
>type : Symbol(type, Decl(exhaustiveSwitchStatementsGeneric1.ts, 6, 13))
18+
}
19+
20+
interface Types {
21+
>Types : Symbol(Types, Decl(exhaustiveSwitchStatementsGeneric1.ts, 8, 1))
22+
23+
a: A;
24+
>a : Symbol(a, Decl(exhaustiveSwitchStatementsGeneric1.ts, 10, 17))
25+
>A : Symbol(A, Decl(exhaustiveSwitchStatementsGeneric1.ts, 0, 0))
26+
27+
b: B;
28+
>b : Symbol(b, Decl(exhaustiveSwitchStatementsGeneric1.ts, 11, 7))
29+
>B : Symbol(B, Decl(exhaustiveSwitchStatementsGeneric1.ts, 4, 1))
30+
}
31+
32+
export function exhaustiveSwitch<T extends keyof Types>(type: T): boolean {
33+
>exhaustiveSwitch : Symbol(exhaustiveSwitch, Decl(exhaustiveSwitchStatementsGeneric1.ts, 13, 1))
34+
>T : Symbol(T, Decl(exhaustiveSwitchStatementsGeneric1.ts, 15, 33))
35+
>Types : Symbol(Types, Decl(exhaustiveSwitchStatementsGeneric1.ts, 8, 1))
36+
>type : Symbol(type, Decl(exhaustiveSwitchStatementsGeneric1.ts, 15, 56))
37+
>T : Symbol(T, Decl(exhaustiveSwitchStatementsGeneric1.ts, 15, 33))
38+
39+
switch (type) {
40+
>type : Symbol(type, Decl(exhaustiveSwitchStatementsGeneric1.ts, 15, 56))
41+
42+
case "a":
43+
return true;
44+
case "b":
45+
return true;
46+
}
47+
}
48+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/exhaustiveSwitchStatementsGeneric1.ts] ////
2+
3+
=== exhaustiveSwitchStatementsGeneric1.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/986
5+
6+
interface A {
7+
type: "a";
8+
>type : "a"
9+
}
10+
11+
interface B {
12+
type: "b";
13+
>type : "b"
14+
}
15+
16+
interface Types {
17+
a: A;
18+
>a : A
19+
20+
b: B;
21+
>b : B
22+
}
23+
24+
export function exhaustiveSwitch<T extends keyof Types>(type: T): boolean {
25+
>exhaustiveSwitch : <T extends keyof Types>(type: T) => boolean
26+
>type : T
27+
28+
switch (type) {
29+
>type : T
30+
31+
case "a":
32+
>"a" : "a"
33+
34+
return true;
35+
>true : true
36+
37+
case "b":
38+
>"b" : "b"
39+
40+
return true;
41+
>true : true
42+
}
43+
}
44+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/typescript-go/issues/986
5+
6+
interface A {
7+
type: "a";
8+
}
9+
10+
interface B {
11+
type: "b";
12+
}
13+
14+
interface Types {
15+
a: A;
16+
b: B;
17+
}
18+
19+
export function exhaustiveSwitch<T extends keyof Types>(type: T): boolean {
20+
switch (type) {
21+
case "a":
22+
return true;
23+
case "b":
24+
return true;
25+
}
26+
}

0 commit comments

Comments
 (0)