How do I check that a switch block is exhaustive in TypeScript?

前端 未结 10 898
伪装坚强ぢ
伪装坚强ぢ 2020-12-02 10:57

I have some code:

enum Color {
    Red,
    Green,
    Blue
}

function getColorName(c: Color): string {
    switch(c) {
        case Color.Red:
                     


        
相关标签:
10条回答
  • 2020-12-02 11:38

    typescript-eslint has "exhaustiveness checking in switch with union type" rule:
    @typescript-eslint/switch-exhaustiveness-check

    0 讨论(0)
  • 2020-12-02 11:41

    To avoid Typescript or linter warnings:

        default:
            ((_: never): void => {})(c);
    

    in context:

    function getColorName(c: Color): string {
        switch(c) {
            case Color.Red:
                return 'red';
            case Color.Green:
                return 'green';
            default:
                ((_: never): void => {})(c);
        }
    }
    

    The difference between this solution and the others is

    • there are no unreferenced named variables
    • it does not throw an exception since Typescript will enforce that the code will never execute anyway
    0 讨论(0)
  • 2020-12-02 11:44

    You don't need to use never or add anything to the end of your switch.

    If

    • Your switch statement returns in each case
    • You have the strictNullChecks typescript compilation flag turned on
    • Your function has a specified return type
    • The return type is not undefined or void

    You will get an error if your switch statement is non-exhaustive as there will be a case where nothing is returned.

    From your example, if you do

    function getColorName(c: Color): string {
        switch(c) {
            case Color.Red:
                return 'red';
            case Color.Green:
                return 'green';
            // Forgot about Blue
        }
    }
    

    You will get the following compilation error:

    Function lacks ending return statement and return type does not include undefined.

    0 讨论(0)
  • 2020-12-02 11:45

    As a nice twist on Ryan's answer, you can replace never with an arbitrary string to make the error message more user friendly.

    function assertUnreachable(x: 'error: Did you forget to handle this type?'): never {
        throw new Error("Didn't expect to get here");
    }
    

    Now, you get:

    return assertUnreachable(c);
           ~~~~~~~~~~~~~~~~~~~~~
           Type "Color.Blue" is not assignable to type "error: Did you forget to handle this type?"
    

    This works because never can be assigned to anything, including an arbitrary string.

    0 讨论(0)
提交回复
热议问题