TS 中内置了一个叫做 Partial的类型,它的作用是把一个类型中的成员设置为可选。例如:

    1. type Todo = {
    2. title: string;
    3. description: string;
    4. };

    Todo中有两个成员,分别是 titledescription,如果把这个类型赋值给 params,那么 params必须包含 titledescription 这两个成员。

    1. const params: Todo = {
    2. title: "title",
    3. description: "description",
    4. };

    如果我们需要让 Todo 中的成员变成可选,可以使用 Partial 进行转换。

    1. const params: Partial<Todo> = {
    2. description: "desc",
    3. };

    这个用法,我一般用于对象合并,例如:

    1. type Todo = {
    2. title: string;
    3. description: string;
    4. };
    5. const updateTodo = (todo: Todo, fieldsToUpdate: Partial<Todo>) => {
    6. return { ...todo, ...fieldsToUpdate };
    7. };
    8. const todo1: Todo = {
    9. title: "title",
    10. description: "description",
    11. };
    12. const todo2 = updateTodo(todo1, {
    13. description: "desc",
    14. });

    如果,我们现在在 Todo类型中,添加一个 states 的成员,它是一个对象。如果想把 states 中的属性也变为可选的,那么 Partial 就无法做到了。
    image.png
    可以从上面的图中发现,Partial只是把 states变成了可选,但是,没有把 states中的属性变成可选。我们可以自己写一个简单 DeepPartial类型来解决这个问题。

    在写之前,先来看看 Partial在 TS 内部是如何实现的。

    1. /**
    2. * Make all properties in T optional
    3. */
    4. type Partial<T> = {
    5. [P in keyof T]?: T[P];
    6. };

    可以看到,Partial 内部通过遍历所有属性,将属性都设置成了可选。

    实现思路是,判断属性值T[P]的类型是否是 object,如果是,在进行一次遍历。

    1. type MyDeepPartial<T> = {
    2. [P in keyof T]?: T[P] extends object ? MyDeepPartial<T[P]> : T[P];
    3. }

    源码:TypeScript Playgroun