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

Conditional type produced different behavior when used in generic type #55610

Closed
unional opened this issue Sep 2, 2023 · 7 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@unional
Copy link
Contributor

unional commented Sep 2, 2023

πŸ”Ž Search Terms

conditional type, generic type, behavior

πŸ•— Version & Regression Information

tested on 5.2.2

⏯ Playground Link

https://www.typescriptlang.org/play?#code/C4TwDgpgBAGlC8UB2EBuEBOUIA9gSQBMBnKAewCMArCAY2CgH4pgMBXaALigDMBDADbEIAKBGhIUAEoAeACoA+BFDnY8BEuWp0GzVhyjd+Q0ePDQAmstkp0GBSKA

πŸ’» Code

type X = never extends object ? true : false // true

type R<T> = T extends object ? true : false

type Y = R<never> // never

πŸ™ Actual behavior

type X = never extends object ? true : false // true

type R<T> = T extends object ? true : false

type Y = R<never> // never

πŸ™‚ Expected behavior

type X = never extends object ? true : false // true

type R<T> = T extends object ? true : false

type Y = R<never> // true

Additional information about the issue

No response

@jcalz
Copy link
Contributor

jcalz commented Sep 2, 2023

#23182

@unional
Copy link
Contributor Author

unional commented Sep 3, 2023

Yes it is the same issue. But this case is even harder to reason because when it is not a generic type, it is evaluated as an empty set, but with generic type, it is evaluated as an empty union.

@fatcerberus
Copy link

fatcerberus commented Sep 3, 2023

Yes it is the same issue. But this case is even harder to reason because when it is not a generic type, it is evaluated as an empty set, but with generic type, it is evaluated as an empty union.

You're overthinking it--never is always best thought of as an empty union. The observed difference in behavior is down to whether the conditional type distributes over it or not, just like with any other union type. That happens whenever the input to the conditional type is a single naked type parameter.

@MartinJohns
Copy link
Contributor

Yes it is the same issue. But this case is even harder to reason because when it is not a generic type, it is evaluated as an empty set, but with generic type, it is evaluated as an empty union.

When it's a generic type it's evaluated distributive, when it's not a generic type it's not.

@unional
Copy link
Contributor Author

unional commented Sep 3, 2023

Yes, maybe.

What I'm really dealing with is defining types with straight forward behavior over the special types: any, unknown, never, (and void).

For example:

type Merge<A extends Record<any, any>, B extends Record<any, any>> = ...

Merge<{ a: 1 }, any>
Merge<{ a: 1 }, never> // this is allowed due to the issue here, I think

I found myself needs to add special handling for never of every type, as the type constraint always allow never to go through.

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Sep 5, 2023
@typescript-bot
Copy link
Collaborator

This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Sep 8, 2023
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

6 participants