srn
srn

Reputation: 170

Why is this TypeScript exhaustive switch check not working?

Why does the following switch default case not lead to an exhaustive check where item is correctly identified as never?

enum Type {
    First,
    Second
}

interface ObjectWithType {
    type: Type;
}

const array: ObjectWithType[] = [];

for (const item of array) {
    switch (item.type) {
        case Type.First:
            break;
        case Type.Second:
            break;
        default: {
            const unhandledItem: never = item;
            throw new Error(`Unhandled type for item: ${unhandledItem}`);
        }
    }
}

Typescript playground link

Upvotes: 1

Views: 2745

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1075129

As @thedude said, the problem is that you're using item instead of item.type.

You can correct the problem and make the code simpler by grabbing type from item early and then using that; in the default, the type of type will automatically be narrowed to never:

for (const item of array) {
    const {type} = item;
    switch (type) {
        case Type.First:
            break;
        case Type.Second:
            break;
        default: {
            throw new Error(`Unhandled type for item: ${type}`);
            // The type here is automatically narrowed  ^^^^  to `never`
        }
    }
}

Playground link

Upvotes: 4

thedude
thedude

Reputation: 9812

It's not working because it's not the item that has never type, it's the item.type.

If you modify your code like so, it will work:

const unhandledItem: never = item.type;
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^

Upvotes: 1

Related Questions