Skip to content

Union not properly narrowed in false side of type conditional  #52172

Closed
@wbt

Description

@wbt

Bug Report

🔎 Search Terms

Union narrowing conditional false

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about common 'bugs' that aren't bugs
  • Nightly version as of test time: v5.0.0-dev.20230109

⏯ Playground Link

Playground link with relevant code

💻 Code

(Note: naming conventions may be a bit inconsistent in this toy example with a smaller, more general-knowledge, domain)

//Types widely used throughout application; expansion would be incorrect
type G7Capital = {
    CA: 'Ottawa'; FR: 'Paris'; DE: 'Berlin'; IT: 'Rome';
    JP: 'Tokyo'; UK: 'London'; US: 'Washington DC'; EU: 'Brussels';
}
type G7Abbreviation = keyof G7Capital;
//Type used only in a few functions for handling a legacy edge case:
type G8Capital<A extends G7Abbreviation | 'RU'> = (
    //Error ts(2536): Type 'A' cannot be used to index type 'G7Capital'.
    //but on the side of the conditional where A is found, 'RU' *should be*
    //narrowed out (it is not: that's the bug reported here)
    //and that would make A === G7Abbreviation === keyof G7Capital
    //which can be used to index 'G7Capital' so there should be no error.
    A extends 'RU' ? 'Moscow' : G7Capital[A]
    //A workaround is flipping the conditional order,
    //but it's not intiutive to try this, expected to behave the same:
    //A extends G7Abbreviation ? G7Capital[A] : 'Moscow'
);

🙁 Actual behavior

In its last uncommented instance, A is still of type G7Abbreviation | 'RU' instead of just G7Abbreviation producing error ts(2536): Type 'A' cannot be used to index type 'G7Capital'.

🙂 Expected behavior

On the side of the conditional where A is found, 'RU' should be narrowed out (it is not: that's the bug reported here) and that would make A === G7Abbreviation === keyof G7Capital which can be used to index 'G7Capital' so there should be no error.
Also, flipping the conditional sequence as seen in the workaround should not make a substantive difference in any conditional expression where either side of the conditional can be described with relative ease.

Deduplication discussion

Not a duplicate of #44401 as it is not fixed by #44771, nor of #44382 as it did not change between versions 4.2.3 and 4.3.2. This is also not a duplicate of issues around control flow analysis, especially with the optional chaining or ternary operators in control-flow analysis of JavaScript.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions