Skip to content

Discriminated union fails in if statements #46763

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

Closed
imdavidmin opened this issue Nov 10, 2021 · 3 comments
Closed

Discriminated union fails in if statements #46763

imdavidmin opened this issue Nov 10, 2021 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@imdavidmin
Copy link

Bug Report

πŸ”Ž Search Terms

Discriminated union, if, if condition, conditional statements

πŸ•— Version & Regression Information

4.4.4

⏯ Playground Link

Playground Link

πŸ’» Code

type FailedTest = { status: '1' | '3' } | FailedTestSpecial
type FailedTestSpecial = { status: '2', data: '2' }
const FailedInput = [] as Array<FailedTest>
const FailedOutput = [] as Array<FailedTestSpecial>

if (FailedInput[0].status == '1' || FailedInput[0].status == '3') {
  FailedInput[0].data // This works as exected.
} else {
  FailedInput[0].status
  FailedOutput.push(FailedInput[0])
}


// Declared now as status 1 and 3 separately
type PassedTest = { status: '1' } | PassedTestSpecial | { status: '3' }
type PassedTestSpecial = { status: '2', data: '2' }
const passedInput = [] as Array<PassedTest>
const passedOutput = [] as Array<PassedTestSpecial>

if (passedInput[0].status == '1' || passedInput[0].status == '3') {
  passedInput[0].data // This works as exected.
} else {
  passedInput[0].status
  passedOutput.push(passedInput[0])
}

πŸ™ Actual behavior

In the failed test, at else in the if block, Typescript understands the status key could only be '2' (mouse hover over .status shows the info), but could not infer from this that the type must be FailedTestSpecial type.
In the passed test, with only the change in how PassedTest is defined by separating {status: '1' | '3'} to {status: '1'} | {status: '3'}, Typescript can now tell the discriminated union in if block.

πŸ™‚ Expected behavior

FailedTest to pass, by inferring the type must be FailedTestSpecial type.

@imdavidmin
Copy link
Author

Discord for Typescript tells me that type FailedTest = { status: '1' | '3' } | FailedTestSpecial will not form a discriminated union and only the other way is the correct way to form it.

If this is the case, then I guess this isn't a bug. But in my mind this is very unintuitive, as Typescript is clearly able to infer that only one status code is possible in the else block.

Perhaps this can be turned into a feature suggestion, if this behaviour is not a bug?

@MartinJohns
Copy link
Contributor

Duplicate of #43026.

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Nov 11, 2021
@imdavidmin
Copy link
Author

Continuing in #43026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants