Microsoft/TypeScript

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

Open

#53,736 opened on Apr 11, 2023

 (2 comments) (0 reactions) (0 assignees)TypeScript (13,395 forks)batch import
Experience EnhancementHelp WantedSuggestion

Repository metrics

Stars
 (108,860 stars)
PR merge metrics
 (Avg merge 6d 17h) (9 merged PRs in 30d)

Description

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