Skip to content

Can I get "narrowing to never" behavior on a non-union type? #46978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cakoose opened this issue Dec 1, 2021 · 3 comments
Closed

Can I get "narrowing to never" behavior on a non-union type? #46978

cakoose opened this issue Dec 1, 2021 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@cakoose
Copy link

cakoose commented Dec 1, 2021

Bug Report

🔎 Search Terms

narrow non-union never
narrow record never

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about "narrow" and "never".

(I tested on the Playground with v3.3.3333, v4.0.5, v4.6.0-dev.20211201.)

⏯ Playground Link

Playground link with relevant code

💻 Code

export function impossible(_value: never): never {
    throw new Error('impossible! (according to static types)');
}

// This is how we define errors for some of our operations.
export type Operation1Error =
    | {type: 'not_found'}
    | {type: 'not_authorized', details: string};

// We use this pattern to handle errors. If someone adds a new option to
// Operation1Error, TS will tell us we need another branch.
function f1(err: Operation1Error): void {
    if (err.type === 'not_found') {
        // ...
    } else if (err.type === 'not_authorized') {
        // ...
    } else {
        throw impossible(err);
    }
}

// Some of our operations currently have just a single type of error.
export type Operation2Error =
    | {type: 'not_found'}

// This doesn't work as well -- TS doesn't allow us to use the same pattern.
function f2(err: Operation2Error): void {
    if (err.type === 'not_found') {
        // ...
    } else {
        // TS error: Argument of type '{ type: "not_found"; }' is not assignable to parameter of type 'never'.
        throw impossible(err);
    }
}

🙁 Actual behavior

In f2, I get a type error on impossible(err). (See comment in code sample.)

🙂 Expected behavior

In f2, I was hoping that err gets narrowed to never and I don't get a type error when using impossible(err).

@MartinJohns
Copy link
Contributor

Duplicate of #38963.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Dec 1, 2021
@RyanCavanaugh
Copy link
Member

If you have something that is currently 1 case but will eventually be more than 1, you can use a workaround

export type Operation2Error =
    | {type: 'not_found'}
    | {type: never}

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants