Closed
Description
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
type Foo = { tag: 'n'; val: number } | { tag: 's'; val: string }
one wants to be able to write a type operator
type Lookup<T extends Foo['tag']> = // ???
such that Lookup<'n'>
= number
and Lookup<'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:
type Lookup = {
n: number
s: string
}
type Foo = {
[T in keyof Lookup]: { tag: T; val: Lookup[T] }
}[keyof Lookup]
then the inferred type of Foo
is
type Foo = {
tag: "n";
val: number;
} | {
tag: "s";
val: string;
}
as desired, and we have our lookup type: Lookup['n']
= number
and Lookup['s']
= string
.
So I use this pattern a lot, and I wanted to generalize it:
type Unionize<Lookup> = {
[T in keyof Lookup]: { tag: T; val: Lookup[T] }
}[keyof Lookup]
Unfortunately, this doesn't do what you want:
type Foo = Unionize<{
n: number
s: string
}>
Here, Foo
is inferred to be
type Foo = {
tag: "n" | "s";
val: string | number;
}
This seems like a bug!