如何解决带循环引用对象的NestedKeyof类型循环引用报错?
解决TypeScript中NestedKeyOf类型处理循环引用对象的报错问题
问题背景
我正在构建一个库,尝试实现NestedKeyof类型,找到了一段可正常运行的代码:
type NestedKeyOf<T extends object> = { [Key in keyof T & (string | number)]: T[Key] extends object ? `${Key}` | `${Key}.${NestedKeyOf<T[Key]>}` : `${Key}` }[keyof T & (string | number)];
但在处理带有循环引用对象时,出现了如下报错:
Type of property 'self' circularly references itself in mapped type '{ [Key in "self" | "name" | "imageManagerIdentifier" | "x"]: Cirulare[Key] extends object ?
${Key}|${Key}.${NestedKeyOf<Cirulare[Key]>}:${Key}; }'.(2615)
完整测试代码如下:
class Cirulare { name: string; self: Cirulare; public imageManagerIdentifier = 'ImageHandler'; x: number; constructor() { this.name = 'asd'; this.self = this; this.x = 0; } } type NestedKeyOf<T extends object> = { [Key in keyof T & (string | number)]: T[Key] extends object ? `${Key}` | `${Key}.${NestedKeyOf<T[Key]>}` : `${Key}` }[keyof T & (string | number)]; const fn<T> = (keys: NestedKeyOf<T>[])=> { } fn<Cirulare>(["name",...])
请问是否有办法禁用该警告/错误或简单解决此问题?
解决方案
方法一:通过条件类型中断循环引用
在递归时引入额外泛型参数记录最外层原类型,当遇到与原类型一致的子类型时停止递归,避免无限循环:
type NestedKeyOf<T extends object, U = T> = { [Key in keyof T & (string | number)]: T[Key] extends object ? T[Key] extends U ? `${Key}` // 匹配到循环引用时终止递归 : `${Key}` | `${Key}.${NestedKeyOf<T[Key], U>}` : `${Key}` }[keyof T & (string | number)];
这个方案可以自动识别循环引用,无需硬编码特定属性,通用性较强。
方法二:临时禁用类型检查(不推荐)
如果只是想快速绕过这个错误,可以在tsconfig.json中开启skipLibCheck编译选项:
{ "compilerOptions": { "skipLibCheck": true } }
注意:该选项会跳过所有库文件的类型检查,可能掩盖其他潜在问题,仅建议临时应急使用。
方法三:手动排除循环引用属性
如果明确知道哪些属性是循环引用的,可以在映射类型中直接排除:
type NestedKeyOf<T extends object> = { [Key in Exclude<keyof T & (string | number), 'self'>]: T[Key] extends object ? `${Key}` | `${Key}.${NestedKeyOf<T[Key]>}` : `${Key}` }[Exclude<keyof T & (string | number), 'self'>];
此方案需要硬编码排除的属性,适合结构固定的对象,但通用性较差。
内容的提问来源于stack exchange,提问作者Alen.Toma
相关产品推荐
相关产品推荐

