-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Incorrect union type inferred #17930
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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: