I already know that that keyof TCreate produces literal union of its keys in the type TCreate. But I’m confused about what TCreate[keyof TCreate] represents.
Why do we write it this way?
How does it work in TypeScript?
Why does it produce a union of all possible value types, instead of preserving the mapping between a specific key and its corresponding value type? For example, given this type:
type TCreate = {
id: number;
name: string;
active: boolean;
};
keyof TCreate gives "id" | "name" | "active"
TCreate[keyof TCreate] gives number | string | boolean.
I think I expected it to somehow keep the relationship like
["id", number] | ["name", string] | ["active", boolean]
instead of collapsing everything into a union.
Could someone explain why it works this way??
I’m confused about what
TCreate[keyof TCreate]represents.Why do we write it this way?
How does it work in TypeScript?
The type syntax A[B] is called an "indexed access type". It pulls out the property type(s) of A corresponding to the key(s) B. For example:
type A = { key1: string; key2: number; key3: boolean }
type Example = A['key1']
// ^? - type Example = string
This works when the key is a union type as well. For example:
type A = { key1: string; key2: number; key3: boolean }
type Example = A['key1' | 'key2']
// ^? - type Example = string | number
You already know that keyof A gets a union type representing all the keys of A. Combining that with what I've explained above, A[keyof A] will resolve to a union of all the property value types of A. For example:
type A = { key1: string; key2: number; key3: boolean }
type Example = A[keyof A]
// ^? - type Example = string | number | boolean
In the above example, keyof A is 'key1' | 'key2' | 'key3', so A[keyof A] is the same as A['key1' | 'key2' | 'key3'].
I think I expected it to somehow keep the relationship like
["id", number] | ["name", string] | ["active", boolean]
A type like that could be derived by mapping over the properties of the initial type. For example:
type A = { key1: string; key2: number; key3: boolean }
type Example = { [K in keyof A]: [K, A[K]] }[keyof A]
// ^? - type Example = ["key1", string] | ["key2", number] | ["key3", boolean]