Skip to content
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

Incorrect discriminated union narrowing following exhaustive if/else #9246

Closed
DanielRosenwasser opened this issue Jun 18, 2016 · 2 comments
Closed
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@DanielRosenwasser
Copy link
Member

type Shape = { kind: "Circle"; radius: number }
           | { kind: "Rectangle"; width: number; height: number }


function area(s: Shape) {
    if (s.kind === "Circle") {
        return s.radius ** 2;
    }
    else if (s.kind === "Rectangle") {
        return s.width * s.height;
    }
    return assertNever(s);
}

function assertNever(x: never): never {
    return x;
}

Expected: No error
Actual:

test.ts(12,24): error TS2345: Argument of type '{ kind: "Circle"; radius: number; }' is not assignable to parameter of type 'never'.
@DanielRosenwasser DanielRosenwasser added the Bug A bug in TypeScript label Jun 18, 2016
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 2.0 milestone Jun 18, 2016
@ahejlsberg
Copy link
Member

This is by design. It is an effect of #8548.

@ahejlsberg ahejlsberg added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Bug A bug in TypeScript labels Jun 18, 2016
@ahejlsberg
Copy link
Member

This one will be tricky to fix. We basically have two conflicting goals: Sometimes we want to use control flow analysis to prove exhaustiveness, at other times we want a convenient way to defeat the exhaustiveness (e.g. when writing defensive code or when control flow analysis can't see the entire picture).

Part of the problem is that we can't always see the "connectedness" of multiple type guards. In a switch statement it is pretty obvious that all of the cases are part of the same test, and it is therefore reasonable to allow an exhaustive check to produce the never type. But with multiple if statements it gets harder because they could be written as a single connected if ... else if ... else if ... else or as multiple separate ifs, possibly with intervening code. Logically it is all the same, but the intent may have been different.

@DanielRosenwasser DanielRosenwasser added Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. In Discussion Not yet reached consensus and removed Working as Intended The behavior described is the intended behavior; this is not a bug labels Jun 24, 2016
@mhegazy mhegazy removed this from the TypeScript 2.0 milestone Jun 28, 2016
@mhegazy mhegazy added Suggestion An idea for TypeScript and removed In Discussion Not yet reached consensus labels Jun 28, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants