Skip to content

Erroneous control flow type narrowing in loops #15835

Closed

Description

TypeScript Version: 2.3.2

Code

const enum Escape {None, Any}

function scan(): void {
    let escape: Escape = Escape.None;

    while (true) {
        // Error: Operator '===' cannot be applied to types 'Escape.None' and 'Escape.Any'.
        escape = escape === Escape.Any ? Escape.None : Escape.Any;
    }
}

Expected behavior:

The type to be correctly broadened, since it's in a loop.

Actual behavior:

The error denoted in the code comment above the line in question.

Activity

  1. dead-claudia commented on May 14, 2017

    @dead-claudia
    Author

    Note that neither of these variants reproduce the bug:

    // Variant 1
    const enum Escape {None, Any}
    
    function scan(): void {
        let escape = Escape.None as Escape;
    
        while (true) {
            escape = escape === Escape.Any ? Escape.None : Escape.Any;
        }
    }
    
    // Variant 2
    function scan(): void {
        let escape = false;
    
        while (true) {
            escape = escape === true ? false : true;
        }
    }

    My current workaround is casting the escape in the condition, like in this:

    const enum Escape {None, Any}
    
    function scan(): void {
        let escape: Escape = Escape.None;
    
        while (true) {
            // No error here
            escape = (escape as Escape) === Escape.Any ? Escape.None : Escape.Any;
        }
    }

    Also, note that in my code, I have about 8-10 cases, for a while/switch-based finite state machine loop.

  2. JShabtai commented on Mar 15, 2018

    @JShabtai

    I just noticed what I believe is the same bug, but without the loop:

    enum MyEnum {
        Foo,
        Bar
    }
    
    class MyClass {
        private state: MyEnum;
    
        // Set state to Bar
        private modify(){
            this.state = MyEnum.Bar;
        }
    
        public fn() {
            this.state = MyEnum.Foo
    
            this.modify();
    
            if (this.state === MyEnum.Bar) {
                // Do stuff here...
            }
        }
    }

    This produces the following error

    tmp.ts(19,13): error TS2365: Operator '===' cannot be applied to types 'MyEnum.Foo' and 'MyEnum.Bar'.
    

    Just tested this with tsc version 2.7.2

    Seems that typescript doesn't think that variables of enum type can ever change?

  3. dead-claudia commented on Mar 16, 2018

    @dead-claudia
    Author

    Josh (@JShabtai) Yours is subtly different:

    • Mine is purely with local variables, where yours is with properties.
    • Yours could change between checks, where mine theoretically couldn't.
  4. RyanCavanaugh commented on Mar 5, 2024

    @RyanCavanaugh
    Member

    Works now. Other comment is a dupe of 9998

  5. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions