TypeScript 4.7.4中嵌套键工具类型抛出TS2589错误如何解决?
解决TypeScript 4.7+中NestedKeyOf类型实例化过深的问题
你编写的NestedKeyOf工具类型用于提取对象的嵌套键路径,在TypeScript 4.3.5中能正常运行,但到了4.7.4版本会触发TS2589: Type instantiation is excessively deep and possibly infinite错误。这是因为TypeScript 4.7+对递归条件类型的检测变得更严格,默认递归深度限制被收紧,深层嵌套对象的类型推导会触发溢出。
解决方案:添加递归深度限制
通过引入可选的深度控制参数,结合辅助类型实现递归层数限制,同时利用TypeScript的条件类型延迟实例化特性绕过过深检测。修改后的代码如下:
type NestedKeyOf<ObjectType extends Record<string, unknown>, Depth extends number = 10> = Depth extends 0 ? never : { [Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends Record<string, unknown> ? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key], Decrement<Depth>>}` : `${Key}` }[keyof ObjectType & (string | number)]; // 辅助类型:实现数字类型减1 type Decrement<N extends number> = N extends 1 ? 0 : N extends 2 ? 1 : N extends 3 ? 2 : N extends 4 ? 3 : N extends 5 ? 4 : N extends 6 ? 5 : N extends 7 ? 6 : N extends 8 ? 7 : N extends 9 ? 8 : N extends 10 ? 9 : number;
关键优化点:
- 深度限制参数:新增
Depth参数(默认值设为10),递归到指定深度时停止,返回never终止递归。你可以根据实际业务中对象的嵌套层数调整这个默认值。 - Decrement辅助类型:实现数字类型的减1操作,每递归一层就将深度减1,直到触发终止条件。
- 延迟实例化:用对象映射类型包裹递归逻辑,让TypeScript在需要时才实例化嵌套类型,而非提前展开所有递归层级,避免触发过深检测。
备选方案:固定层数展开
如果你的业务场景中对象嵌套层数固定且不深,也可以直接展开固定层数的递归,这种方式更简单但灵活性较差:
type NestedKeyOf<T extends Record<string, unknown>> = | keyof T & (string | number) | `${keyof T & (string | number)}.${keyof T[keyof T] & (string | number)}` | `${keyof T & (string | number)}.${keyof T[keyof T] & (string | number)}.${keyof T[keyof T][keyof T[keyof T]] & (string | number)}`;
修改后的类型在TypeScript 4.7.4及更高版本中可正常编译,同时保留原有的嵌套键提取功能。
内容的提问来源于stack exchange,提问作者JIyHaTuK
相关产品推荐
相关产品推荐

