为何TypeScript不对深度嵌套类型的赋值进行校验?
TypeScript递归嵌套类型赋值校验失效问题
我为表单场景创建了一套支持递归嵌套的错误类型结构,代码如下:
type ErrorNodeDetails = {example: number} type ErrorNode<FormData> = FormData extends Array<infer ArrayItem> ? ErrorNode<ArrayItem> : FormData extends Primitive ? ErrorNodeDetails : ErrorNodeDetails & { children?: Readonly<{ [K in keyof FormData]?: ErrorNode<FormData[K]> }> } export type ErrorMap<FormData extends Record<string, unknown>> = { [K in keyof FormData]?: ErrorNode<FormData[K]> }
这套类型在访问时行为完全符合预期:TypeScript会自动补全合法键,且禁止访问非法键。但在赋值环节,当嵌套层级超过一定深度后,类型校验会失效:
const x: ErrorMap<{ x: { d: { c: 1 } } }> = { x: { example: 1, children: { d: { children: { // 此层级前TS会严格校验,比如不能把children改成c c1: { s: 1 }, // c1是非法键,但TS未拦截这个错误 }, example: 1, }, }, }, } // 访问时正常:TS会自动补全c,且禁止访问c1 x.x?.children?.d?.children?.c
请问这是TypeScript的固有限制,还是我的类型定义存在疏漏?
这是TypeScript的固有递归深度限制,并非你的类型定义有疏漏。
TypeScript为了避免递归类型导致的无限循环和性能损耗,对递归类型的结构校验设置了默认深度阈值(通常在4-5层左右)。在读取/访问类型时,TS采用惰性推导,只会在需要的时候解析对应层级的类型,所以能正常提供补全和校验;但在赋值时,TS需要主动遍历整个对象结构进行类型匹配,当嵌套层级超过阈值后,会自动放宽校验规则,允许不符合定义的键存在。
如果需要更严格的深层校验,可以尝试以下方案:
- 拆分复杂嵌套类型,将深层结构抽离为独立类型,减少单类型的递归深度
- 在
tsconfig.json中调整strict相关配置(如strictNullChecks),但这可能无法完全突破深度限制,还可能影响整体编译性能 - 手动为深层结构添加显式类型约束,替代纯递归推导
内容的提问来源于stack exchange,提问作者Thiago Pereira Maia
相关产品推荐
相关产品推荐

