Skip to content

Incorrect narrowing of union to never after no-op switch in while loop #47539

@RyanCavanaugh

Description

@RyanCavanaugh

Bug Report

🔎 Search Terms

switch while union never

🕗 Version & Regression Information

Playground link with relevant code

💻 Code

declare function isNever(n: never): boolean;

function f() {
    let foo: "aaa" | "bbb" = "aaa";
    while (true) {
        switch (foo) {
            case "aaa":
        }

        if (foo === "aaa") {
            foo = "bbb";
        } else if (isNever(foo)) { // incorrect OK
            break;
        }
    }
}

🙁 Actual behavior

The code incorrectly checks as OK.

🙂 Expected behavior

The call to isNever should fail; on the second iteration of the loop isNever is invoked with "bbb"

Note that we don't see this behavior with the equivalent if:

declare function isNever(n: never): boolean;

function f() {
    let foo: "aaa" | "bbb" = "aaa";
    while (true) {
        //switch (foo) {
        //    case "aaa":
        //}
        if (foo === "aaa") { }

        if (foo === "aaa") {
            foo = "bbb";
        } else if (isNever(foo)) { // correct error
            break;
        }
    }
}

See also #47538

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: Control FlowThe issue relates to control flow analysisFix AvailableA PR has been opened for this issueRescheduledThis issue was previously scheduled to an earlier milestone

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions