TS递归类型实战:搞定深层JSON和DeepPartial
很多开发者在处理深层嵌套的JSON或文件树时,习惯性地写
这种方案比写一大堆运行时校验要高效得多,一次定义,整个项目的所有调用方都能享受到类型补全和安全检查。
下一篇
用Streamlit快速搭建销售分析看板 →
any 或者只定义两三层接口,结果在访问 config.theme.colors.primary.default 这种深层路径时,编译器完全没提示,直接在运行时报 undefined 错误。其实只要定义好递归类型,编译器就能在编译阶段强制你处理这些潜在的空值。最典型的就是定义一个能够自我引用的 JSONValue,这样无论嵌套多少层,TS 都能追踪到具体的形状。
一、定义递归基础类型
要实现递归,必须有一个终止条件(Base Case),否则编译器会直接崩溃。
type JSONValue =
| string
| number
| boolean
| null
| { [key: string]: JSONValue }
| JSONValue[];
二、实战:实现 DeepPartial
原生的 Partial<T> 只能把第一层属性变为可选,如果面对复杂的配置对象,我们需要一个能递归处理所有层级的 DeepPartial。
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object
? DeepPartial<T[P]>
: T[P];
};三、关于递归深度限制的避坑指南
在使用过程中,可能会遇到 TS 报错提示递归过深。在 TS 5.6+ 版本中,限制大约在 50 次迭代左右。如果你的数据结构极端复杂,可以尝试以下优化方向:

- 使用分布条件类型(Distributive Conditional Types): 尽量让类型推导在进入递归前先进行分发,减少重复展开。
- 尾递归模式: 调整类型定义顺序,让递归调用处于最后一步,帮助编译器优化展开路径。
- 明确基础类型: 确保
null、unknown或原始类型被优先匹配,尽早终止递归。
这种方案比写一大堆运行时校验要高效得多,一次定义,整个项目的所有调用方都能享受到类型补全和安全检查。
