-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Incorrect union type inferred #17930
Comments
Looking at quickinfo on type Unionize<Lookup> = { tag: keyof Lookup; val: Lookup[keyof Lookup]; } which is "simplified" in the same surprising/incorrect way I see in #17908. I think these are the same underlying issue. |
Workaround? type Unionize<Lookup, X = { [T in keyof Lookup]: { tag: T; val: Lookup[T] } }> = X[keyof X] |
Wow, very cool @gcanti! I didn't realize type parameter defaults could reference previous type parameters. This opens up a whole new world... |
Just gotta say @gcanti's proposal is impressive :)
This is the expected behavior. mapped types are a transformation on properties of a type, they do not generate a union type. Many operations that happen on mapped types e.g. inference, rely on the fact that they are homomorphic transformation. |
@mhegazy: It may be expected behavior if you know how mapped types are implemented, but it's very surprising, as it violates the seemingly airtight principle of composition: type X = ...
type F<T> = ...
type G<T> = ...
type FoG<T> = F<G<T>>
type FGX1 = F<G<X>>
type FGX2 = FoG<X>
// FGX1 should be equivalent to FGX2 Can you explain more about why generating a union type (i.e., Thanks! |
For completeness' sake/History, the workaround was first found by @nirendy / @tycho01 during their exploration in #12215 (ref #12215 (comment), #16018 (comment)). |
unionize should be working now after #15756. |
FYI to anyone who gets here, #21316 now allows you to look up a union type by tag value. |
I've found it frequently desirable to be able to "look up" the union variant associated with a type tag. For example, given a union
one wants to be able to write a type operator
such that
Lookup<'n'>
=number
andLookup<'s'>
=string
.I don't think this is possible in the current type system (would welcome correction on that point). Instead, we can use the trick of starting with a
Lookup
type, and deriving the union type from it:then the inferred type of
Foo
isas desired, and we have our lookup type:
Lookup['n']
=number
andLookup['s']
=string
.So I use this pattern a lot, and I wanted to generalize it:
Unfortunately, this doesn't do what you want:
Here,
Foo
is inferred to beThis seems like a bug!
The text was updated successfully, but these errors were encountered: