Skip to content

tsc gets confused on checking assignability with numeric literals? #44087

Closed

Description

@h-joo

Bug Report

TSC reports This condition will always return 'false' since the types 'A' and '-1' have no overlap.

For a moment I thought this might be another instance of #9998 or #8513, but from my understanding, the compiler ignores the -1 from the union type annotation of abc(A | -1) in , because number is not assignable to -1. So I thought this might be a different issue from #9998 or #8513, since the core issue seems to be that a literal type within a union expression gets ignored.

🔎 Search Terms

🕗 Version & Regression Information

Started to appear from 4.3.0-beta

⏯ Playground Link

Playground link

💻 Code

enum A{
    A0 = 0,    
    A1 = 1,
}
function foo(param:number) {
    const abc : (A | -1) = param;
    if(abc === -1) {
       ~~~~~~~~~ This condition will always return 'false' since the types 'A' and '-1' have no overlap.        
    }
}

🙁 Actual behavior

TSC complains that abc cannot be -1

🙂 Expected behavior

TSC is happy

Activity

  1. changed the title [-]This condition will always return 'false' since the types have no overlap[/-] [+]tsc gets confused on checking assignability with numeric literals?[/+] on May 14, 2021
  2. RyanCavanaugh commented on May 14, 2021

    @RyanCavanaugh
    Member

    This seems likely to be a side effect of having fixed #42442.

  3. RyanCavanaugh commented on May 14, 2021

    @RyanCavanaugh
    Member
  4. ahejlsberg commented on May 14, 2021

    @ahejlsberg
    Member

    Ugh. We permit the assignment of number to A | -1 because, for ancient backwards compatibility reasons, number is assignable to any numeric enum type. Control flow analysis then narrows abc by removing all non-assignable types from its union type, thus believing abc has type A following the initialization. And that type doesn't include -1 so CFA now thinks the condition is always false.

    We need to somehow exclude the number-assignable-to-any-enum rule from our control flow analysis. Ideally CFA sould view the initialization as having an unknown effect, thus not narrowing at all following the initialization.

  5. RyanCavanaugh commented on May 14, 2021

    @RyanCavanaugh
    Member

    I would honestly propose Won't Fix and recommend writing

        const abc = param as (A | -1);

    instead since the assignment is already unsound.

    Piling up the epicycles higher will probably only make things worse.

  6. added
    Won't FixThe severity and priority of this issue do not warrant the time or complexity needed to fix it
    and removed
    BugA bug in TypeScript
    on May 14, 2021
  7. RyanCavanaugh commented on May 14, 2021

    @RyanCavanaugh
    Member

    The disallowment of abc === -1 is a documented breaking change.

    Fixing the narrowing would be very invasive and noisy; we're going to leave this as-is.

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

    Won't FixThe severity and priority of this issue do not warrant the time or complexity needed to fix it

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions