TypeScript Type Challenge Pick Walkthrough
The goal of the challenge is to reimplement the built in Pick generic type that exists in TypeScript, without using Pick itself.
The challenge: https://github.com/type-challenges/type-challenges/blob/main/questions/00004-easy-pick/README.md
Watch the video
An example case
Given the following TypeScript:
interface Todo {
title: string
description: string
completed: boolean
}
type TodoPreview = MyPick<Todo, 'title' | 'completed'>Given the interface Todo above, we need to create a generic type MyPick that takes the type (Todo) and a union of the properties that we wish to pick from it. The base code would look something like:
type MyPick<T, K> = ?Approach
If we were creating a function in JavaScript to do a similar job, we'd want to loop over everything in K and construct a new object with each entry from K as a key. We'd set that key value equal to T[i] to reference the original value of T for that key.
We can do something similar in TypeScript types with mapped types. The syntax for a mapped type is:
type MyPick<T, K> = {
[Property in K]: T[Property]
}Where property is bound to each entry in our K type union.
The solution
The above creates a new type from the existing type T, with only the keys from K in it, as it loops over the entries in K only. However it doesn't work as TypeScript has no guarantee that the type K is a union type. For example:
MyPick<Todo, number>Would not through any TypeScript errors as both T and K are types, Todo and number respectively. Clearly we need to restrict the type of K to be a union type of keys that exist on T.
type MyPick<T, K extends keyof T> = {
[Property in K]: T[Property]
}This means that even if K is a union, if it includes properties that do not exist on T, it will result in a compiler error.