Skip to content
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

Ternary two different types infers to one type when one is a subset of the other #46449

Closed
danielbartsch opened this issue Oct 20, 2021 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@danielbartsch
Copy link

Bug Report

🔎 Search Terms

ternary type union

Maybe related: #33070, #20863

🕗 Version & Regression Information

⏯ Playground Link

Playground link with relevant code

💻 Code

type A = { a: number; b: string }
type B = { a: number }
  
const a: A = { a: 5, b: '' }
const b: B = { a: 10 }

// ab infers as B, should be A | B
const ab = Math.random() > 0.5 ? a : b

🙁 Actual behavior

ab infers to B

🙂 Expected behavior

ab should infer to A | B

@fatcerberus
Copy link

This is normal subtype reduction and is by design, as far as I know.

@andrewbranch andrewbranch added the Working as Intended The behavior described is the intended behavior; this is not a bug label Oct 20, 2021
@fatcerberus
Copy link

To be fair there is a downside to this kind of subtype reduction: "b" in ab no longer works to recover A.

@andrewbranch
Copy link
Member

Yeah, I’ve seen a couple cases like this where subtype reduction is a little unfortunate. Don’t think there’s anything to be done though.

@MartinJohns
Copy link
Contributor

@danielbartsch In that example the variable ab is still typed B, not A | B. Assigning a value to a variable narrows the type of the variable, and you're assigning a value of type B - so ab is of type B. This behaviour is intentional.

If you want to explicitly type it as A | B you can use a type assertion:

const ab: A | B = (Math.random() > 0.5 ? a : b) as A | B

@fatcerberus
Copy link

Well, it would be A | B if it weren't for subtype reduction. That this pattern is broken is exactly what I was pointing out above. Unfortunately, yeah, there's no way to prevent this without a type assertion.

@danielbartsch
Copy link
Author

Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants