TS 中内置了一个叫做 Partial的类型,它的作用是把一个类型中的成员设置为可选。例如:
type Todo = {title: string;description: string;};
Todo中有两个成员,分别是 title 和 description,如果把这个类型赋值给 params,那么 params必须包含 title 和 description 这两个成员。
const params: Todo = {title: "title",description: "description",};
如果我们需要让 Todo 中的成员变成可选,可以使用 Partial 进行转换。
const params: Partial<Todo> = {description: "desc",};
这个用法,我一般用于对象合并,例如:
type Todo = {title: string;description: string;};const updateTodo = (todo: Todo, fieldsToUpdate: Partial<Todo>) => {return { ...todo, ...fieldsToUpdate };};const todo1: Todo = {title: "title",description: "description",};const todo2 = updateTodo(todo1, {description: "desc",});
如果,我们现在在 Todo类型中,添加一个 states 的成员,它是一个对象。如果想把 states 中的属性也变为可选的,那么 Partial 就无法做到了。
可以从上面的图中发现,Partial只是把 states变成了可选,但是,没有把 states中的属性变成可选。我们可以自己写一个简单 DeepPartial类型来解决这个问题。
在写之前,先来看看 Partial在 TS 内部是如何实现的。
/*** Make all properties in T optional*/type Partial<T> = {[P in keyof T]?: T[P];};
可以看到,Partial 内部通过遍历所有属性,将属性都设置成了可选。
实现思路是,判断属性值T[P]的类型是否是 object,如果是,在进行一次遍历。
type MyDeepPartial<T> = {[P in keyof T]?: T[P] extends object ? MyDeepPartial<T[P]> : T[P];}
