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 Tgets the keys from the object typeTinis for iteration over the keysKeyis 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,numberorsymbol - We cannot call
T[Key]ifKeydoesn'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