typescripttype-narrowing

Why doesn't typescript narrow types with control flow and never when using arrow functions


Typescript refuses to narrow with a call to fail but will narrow with a call to fail2. Is this a bug in typescript?

const fail = (message?: string): never => {
    throw new Error(message);
};

function fail2(message?: string): never {
    throw new Error(message);
}

const getData = (): string | null => {
    return "the-data";
}



export const loadDataOrError = (): string => {
    const data = getData();

    if (data === null) {
        // Swap the below and see that it works
         
        // fail2();
        fail();
    }

    // This errors
    return data;
};

here is a playground if you want to try switching the comments and seeing the error vanish.

Screenshots for clarity
With an error

With an error

Without an error

Without an error


Solution

  • According to this open GitHub issue this is a limitation of how type narrowing currently works in typescript. If you want to remedy it you can explicitly annotate arrow function types like so:

    const fail: (message?: string) => never = (message) => {
        throw new Error(message)
    }