Pick type under the hood in TypeScript
1type MyPick<T, Keys> = any; // implementation23type Post = {4 title: string;5 description: string | undefined;6 author: string;7};89type Step1 = MyPick<Post, "title" | "description">;10type Step2 = { title: Post["title"]; description: Post["description"] };11type Result = { title: string; description: string | undefined };
First challenge is Pick
It's usually used when you need to declare the type which is based on another type. And you know in advance which keys are included.
Iteration over an object
First, you need to iterate over an object T
. Usually Mapped Types are used in this case:
1type MappedType<T> = {2 [Key in keyof T]: T[Key];3};
keyof T
gets the keys from the object typeT
in
is for iteration over the keysKey
is a key itselfT[Key]
is a value for a specified Key
Second, to iterate over the part of an object, we need to specify Keys
to iterate over:
1type MappedType<T, Keys> = {2 [Key in Keys]: T[Key];3};
But with this you have 2 errors:
Type 'Keys' is not assignable to type 'string | number | symbol'
Type 'Key' cannot be used to index type 'T'
Both errors are connected with the rules of the iteration:
- Key can be
string
,number
orsymbol
- We cannot call
T[Key]
ifKey
doesn't exist inT
If rule 2 is true, rule 1 will be true as existing keys are one of the specified types. To iterate over the existing keys, we need to apply Generic Constrains using extends
keyword.
This way, if we specify non-existing key, TypeScript will throw an error We cannot call T[Key] if Key doesn't exist in T
so we're safe now ✅
1type MyPick<T, Keys extends keyof T> = {2 [Key in Keys]: T[Key];3};
Check out the solution in Playground – https://tsplay.dev/mZbKem ⭐️
typescript