Microsoft/TypeScript

Switch statement over a union of literals is not exhaustive when checking against enum members

Open

#53.736 geöffnet am 11. Apr. 2023

Auf GitHub ansehen
 (2 Kommentare) (0 Reaktionen) (0 zugewiesene Personen)TypeScript (6.726 Forks)batch import
Experience EnhancementHelp WantedSuggestion

Repository-Metriken

Stars
 (48.455 Stars)
PR-Merge-Metriken
 (Durchschn. Merge 6T 17h) (9 gemergte PRs in 30 T)

Beschreibung

Bug Report

The following switch-case is unexpectedly not exhaustive:

enum X {
    FOO = "foo",
    BAR = "bar"
}

function test(x: "foo" | "bar") {
    switch (x) {
        case X.FOO:
            return x;
        case X.BAR:
            return x;
    }
}

Because X.FOO and X.BAR are just strings under the hood, I would expect this to compile as exhaustive. It's doubly surprising because:

  • Typescript correctly narrows the type of x within each case branch
  • this works if I check directly against the string literals or a const object (e.g. const XConst = { FOO: "foo", BAR: "bar" } as const)

🔎 Search Terms

switch union literals exhaustive enum

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about enum, literals, switch statements, type narrowing

⏯ Playground Link

Playground link with relevant code

💻 Code

enum X {
    FOO = "foo",
    BAR = "bar"
}

const XConst = {
    FOO: "foo",
    BAR: "bar"
} as const;

// does not compile
function test(x: "foo" | "bar") {
    switch (x) {
        case X.FOO:
            return x;
        case X.BAR:
            return x;
    }
}

// compiles
function test2(x: X) {
    switch (x) {
        case X.FOO:
            return x;
        case X.BAR:
            return x;
    }
}

// compiles
function test3(x: "foo" | "bar") {
    switch (x) {
        case "foo":
            return x;
        case "bar":
            return x;
    }
}

// compiles
function test4(x: "foo" | "bar") {
    switch (x) {
        case XConst.FOO:
            return x;
        case XConst.BAR:
            return x;
    }
}

🙁 Actual behavior

function test does not compile

🙂 Expected behavior

Function test compiles

Contributor Guide