Skip to content

Distributive type on generic has surprising results #61169

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
ceymard opened this issue Feb 12, 2025 · 3 comments
Closed

Distributive type on generic has surprising results #61169

ceymard opened this issue Feb 12, 2025 · 3 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ceymard
Copy link

ceymard commented Feb 12, 2025

πŸ”Ž Search Terms

remove generic string type from union containing it with string literals / filter generic string out of union containing literal types

πŸ•— Version & Regression Information

5.7

⏯ Playground Link

No response

πŸ’» Code

type LiteralString<T> = string extends T ? never : T;

type Test1 = LiteralString<string>; // never
type Test2 = LiteralString<"literal">; // "literal"
type Test3 = LiteralString<string | "literal"> // shoud be "literal"

πŸ™ Actual behavior

Test3 ends up being never

πŸ™‚ Expected behavior

Test3 should be "literal"

Additional information about the issue

No response

@jcalz
Copy link
Contributor

jcalz commented Feb 12, 2025

  • That's not a distributive conditional type. In string extends T, the type string is not a generic type parameter, so it is just a plain conditional type, it does not distribute across unions.

  • Even if it were distributive, this could never work; the type string | "literal" is eagerly reduced to string, so there is no way for Test3 to behave differently from Test1, no matter how LiteralString<T> were implemented.

This is not a bug in TypeScript.

@ceymard
Copy link
Author

ceymard commented Feb 12, 2025

Is there a way to prevent that eagerness to keep the literal types ?

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 12, 2025
@jcalz
Copy link
Contributor

jcalz commented Feb 12, 2025

See #29729; you could try things like #29729 (comment) (e.g., (string & {}) | "literal") but that could have weird side effects. Or are other things you can do, like wrapping your types in something else (e.g., [string] | ["literal"]) but again, that would involve some kind of refactoring. In any case this isn't a bug in TS and this is not a general support forum so I'll disengage. Good luck!

@ceymard ceymard closed this as completed Feb 12, 2025
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

3 participants