Skip to content

Empty object in ternary operator produces invalid type #50171

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
olehmisar opened this issue Aug 3, 2022 · 6 comments
Closed

Empty object in ternary operator produces invalid type #50171

olehmisar opened this issue Aug 3, 2022 · 6 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@olehmisar
Copy link

Bug Report

πŸ”Ž Search Terms

empty object, {}, inferred type

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

const x = true ? 'I am a string' : {} // type of `x` is: {}

πŸ™ Actual behavior

Type of x is inferred as {}

πŸ™‚ Expected behavior

Type of x should be inferred as "I am a string" | {}.

For example, if we try this code:

const x = true ? 'I am a string' : 5

...the type of x is inferred as "I am a string" | 5

@MartinJohns
Copy link
Contributor

Strings are valid {}, so the type gets simplified. This is working as intended.

@jcalz
Copy link
Contributor

jcalz commented Aug 4, 2022

See https://www.typescriptlang.org/docs/handbook/type-inference.html#best-common-type

@olehmisar
Copy link
Author

Strings are valid {}, so the type gets simplified. This is working as intended.

why isn't this code simplified?

type X = string | {} // `X` is string | {}

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Aug 4, 2022
@RyanCavanaugh
Copy link
Member

Subtype reduction isn't required to happen, but is allowed to happen at any point. There's not a bug here.

@Jack-Works
Copy link
Contributor

but do you think this type reduction is correct / meaningful to developers?

@poksme
Copy link

poksme commented Dec 6, 2024

I encountered this issue when composing a dynamic object. For anyone seeing this and trying to find a workaround, couple things to note :

  • Subtype reduction happens when assigned to a variable, so you might get away with inlining this code instead of storing it in a variable.
(true ? 'I am a string' : {}) // Type is 'I am a string' | {}
const myVar = true ? 'I am a string' : {} // Type is {}
  • In my case, both return values of the ternary were enumerable, and cloning it with a spread prevented the subtype reduction, even when assigned to a variable.
const computeData = () => ({ foo: "bar"})

const subtypeReduced = true ? computeData() : {}; // Type is {}
const preservedType = {...(true ? computeData() : {}) } // Type is { foo?: string | undefined; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Not a Defect This behavior is one of several equally-correct options
Projects
None yet
Development

No branches or pull requests

6 participants