Let's say we all love ice cream. So we define the following enum in TypeScript:

enum IceCreamTaste {  
  awesome,
  meh,
  dunnoYet
}

And now we want a switch that returns an answer to your friend's question "How does your ice cream taste?". Like so:

function getAnswer(taste: IceCreamTaste) {  
    switch (taste) { 
        case IceCreamTaste.awesome:
            return `It's like a party in my mouth!`;
        case IceCreamTaste.meh:
            return 'Umm I think someone has eaten this before me.';
         case IceCreamTaste.dunnoYet:
            return 'Lemme try it first, ok?';
        default:
            throw new Error('unreachable case');
    } 
}

Now, it sure would be nice if TypeScript could hand-hold us a little and verify that we've covered all the possible values of the IceCreamTaste enum, right? Otherwise if I add, say, a new chocolate taste (which is obviously above awesome), I would have to remember to update all the switches that reference the enum and...oh hey, welcome, bugs!

Unreachability

Fortunately TypeScript 2+ sports a useful type called never (sometime referred to as the "bottom" type) which represents a value that can never occur.

OK, so how is that useful, you ask? Well, because our IceCreamTaste switch is exactly such a case - we want to tell the TypeScript compiler that the default branch of the switch statement is one of those "code execution can never get there" blocks.

Let's define an UnreachableCaseError:

class UnreachableCaseError extends Error {  
    constructor(val: never) { 
        super(`Unreachable case: ${val}`);
    }
}

Now if we plug this error into our ice cream switch, we get this type safe bliss:

function getAnswer(taste: IceCreamTaste) {  
    switch (taste) { 
        case IceCreamTaste.awesome:
            return `It's like a party in my mouth!`;
        case IceCreamTaste.meh:
            return 'Umm I think someone has eaten this before me.';
         case IceCreamTaste.dunnoYet:
            return 'Lemme try it first, ok?';
        default:
            throw new UnreachableCaseError(taste);
    } 
}

Try commenting out one of the cases and TypeScript will report an Argument of type 'IceCreamTaste.dunnoYet' is not assignable to parameter of type 'never' error.

Happy exhaustive switching! I'm @tomasbrambora