TypeScript 如何做深度 Partial

你肯定碰过这种情况:写代码时想把一个复杂对象里的所有属性都变成“可选”的,偏偏普通的 Partial 只能做浅层次的——比如一个嵌套的 user 对象,Partial<User> 只能让 user.name 可选,没法自动让 user.address.city 也变成可选。这时候就得用到“深度 Partial”了,它就是把对象里每一层的属性都递归改成可选,像剥洋葱一样,从外到内每一层都松绑。

为啥普通 Partial 不够用?

举个生活化的例子:你订外卖填地址,外层的 Address 对象有省、市、区、街道,都是必填的。如果用普通 Partial<Address>,你最多能让“省”可选,但“市”“区”还是得填——可万一你只说“我在浙江杭州”,不想填具体区和街道呢?这时候普通 Partial 就卡壳了,它只改最外层,管不了内层,而深度 Partial 就是帮你把所有层级的必填都变成“可填可不填”。

TypeScript 如何做深度 Partial

手写深度 Partial,用递归解决嵌套问题

要做深度 Partial,核心是“递归”——遇到对象就把它的属性也转成深度可选,遇到基本类型就直接留着。我们先写个基础的类型定义:

`typescript

type DeepPartial<T> = {

// 遍历T的每一个属性键K

[K in keyof T]?:

// 判断属性T[K]是不是对象(排除null,因为typeof null也是object)

T[K] extends object

? DeepPartial<T[K]>

: T[K];

};

`

再用刚才的地址模型试试:

`typescript

interface Address {

province: string;

city: string;

detail: {

district: string;

street: string;

};

}

// 用DeepPartial处理后,所有属性都是可选的

const partialAddress: DeepPartial<Address> = {

province: "浙江",

city: "杭州",

// 不用填district、street,也符合类型要求

};

`

这里的递归就是关键:当遇到 detail 这个对象属性时,自动调用 DeepPartial 把它的 district 和 street 也变成可选,完美解决嵌套的问题。

避开两个常见的坑

实际用的时候,容易踩这两个小坑,得留意:

第一个坑:Array 类型别误判。比如地址里的 tags: string[],typeof [] 是 object,如果直接用上面的类型,会把数组的元素也递归转成 DeepPartial——比如 tags 会变成 Array<DeepPartial<string>>,其实我们只需要让数组本身可选,元素还是原来的类型就行。所以要加个判断,排除 Array:

`typescript

type DeepPartial<T> = {

[K in keyof T]?:

T[K] extends Array<any>

? T[K]

: T[K] extends object

? DeepPartial<T[K]>

: T[K];

};

`

这样 tags 还是 string[],不会乱改。

第二个坑:Date 等内置对象也别递归。如果属性是 Date 类型,typeof Date 是 object,但我们不需要把 Date 的属性转成可选,直接保留就行,所以再加个判断:

`typescript

type DeepPartial<T> = {

[K in keyof T]?:

T[K] extends Array<any>

? T[K]

: T[K] extends Function

? T[K]

: T[K] extends object

? DeepPartial<T[K]>

: T[K];

};

`

加完 Function 的判断,那些函数类型的属性也不会被误处理了。

现成工具类也能搞定

如果不想自己手写,很多常用的 TS 工具库(像 utility-types)已经封装好了 DeepPartial,直接导入用就行,适合快速开发的场景。但如果是做项目内部的基础类型定义,自己写一个适配业务需求的,会更灵活。

深度 Partial 本质就是“递归处理嵌套对象的每个层级”,把复杂对象的所有属性都变成可选,刚好对应了实际开发里那种“只传部分数据”的场景,不管是做表单、接口参数还是配置对象,用它都能少写很多冗余代码。

上一篇 Swift编程语言核心特性解析:从基础语法到应用开发的入门科普指南