I’m trying to make a type that converts a record to a union of all the types of it’s keys.
Example:
Given the following type :
type Foo = {
key1: { bar: '1' };
key2: { bar: '2' };
key3: { bar: '3' };
}
I would like to create a type KeysTypeUnion<T> that validates :
KeysTypeUnion<Foo> == { bar: '1' } | { bar: '2' } | { bar: '3' }
I was only able to write it by hand like so:
FooKeysTypeUnion = typeof Foo.key1 | typeof Foo.key2 | typeof Foo.key3
But it would be helpful to make a type alias to save time.
Tests:
KeysTypeUnion<{ key1: '1'; key2: '2'; key3: '3' }> == '1' | '2' | '3'
KeysTypeUnion<Record<string, A | B | C>> == A | B | C
>Solution :
You can create that in at least two different ways, one being a bit more general than the other.
The simple way is this:
type KeysTypeUnion<Foo> = Foo[keyof Foo];
A more complicated way that is more general is this
type KeysTypeUnion<Foo> = Foo extends {[k: string | number | symbol]: infer V} ? V : never;
refer to this post to understand the infer keyword
I think the name you choose is a bit confusing though, as it is the type of the values and not the keys. I mean, if we had an object of type Foo, let’s call it foo, and ran Object.values(foo), then it’s the type of that that your KeysTypeUnion returns. I think ValueOf<Foo> would probably be a better name and mirror the keyof operator and Object.keys() and Object.values(). Though, probably the idiomatic name is Foo[keyof Foo]. It’s pretty short and should be readable 🙂