如何检测对象重叠叶子节点并生成友好编译期错误提示
问题描述
我有两个不应存在共同叶子节点的对象:
const translated = { a: { b: { c: "Hello", d: "World" } } }; const toTranslate = { a: { b: { d: "Everybody" } } };
期望编译时生成错误提示:'a.b.d' 同时存在于两个对象中。
我可以用单元测试检测该问题,但希望在编译期给出友好的错误提示。我的尝试代码如下:
type Leaves<T> = T extends object ? { [K in keyof T]: `${Exclude<K, symbol>}${Leaves<T[K]> extends never ? "" : `.${Leaves<T[K]>}`}` }[keyof T] : never type TranslatedLeaves = Leaves<typeof translated> type ToTranslateLeaves = Leaves<typeof toTranslate> type Overlap = TranslatedLeaves & ToTranslateLeaves type ErrorIfOverlapping<T extends never = Overlap> = void;
但目前仅得到错误提示:Type 'string' does not satisfy the constraint 'never'.,请问是否可以生成包含所有重叠叶子节点的错误提示?
解决方案
要生成包含具体重叠路径的友好错误提示,我们可以通过构造条件类型,在存在重叠路径时返回包含这些路径的错误信息类型,而非仅依赖never约束。
修改后的代码如下:
// 递归获取对象的所有叶子节点路径 type Leaves<T> = T extends object ? { [K in keyof T]: `${Exclude<K, symbol>}${Leaves<T[K]> extends never ? "" : `.${Leaves<T[K]>}`}` }[keyof T] : never; type TranslatedLeaves = Leaves<typeof translated>; type ToTranslateLeaves = Leaves<typeof toTranslate>; // 提取两个叶子节点集合的交集 type Overlap = TranslatedLeaves & ToTranslateLeaves; // 构造错误提示类型:无重叠时返回void,有重叠时返回包含路径的错误信息 type ErrorIfOverlapping = Overlap extends never ? void : `错误:以下叶子节点同时存在于两个对象中:${Overlap}`; // 触发类型检查 type Check = ErrorIfOverlapping;
效果说明
当存在重叠路径(比如示例中的'a.b.d')时,TypeScript会抛出明确的错误:
Type '错误:以下叶子节点同时存在于两个对象中:"a.b.d"' is not assignable to type 'void'.
错误信息直接包含了具体的重叠路径,完全符合需求。
原理说明
Leaves<T>保持原有逻辑,负责递归生成所有叶子节点的字符串路径;Overlap通过交集类型提取两个路径集合的共同部分;ErrorIfOverlapping利用条件类型判断:- 若
Overlap为never(无重叠),则返回void,无编译错误; - 若存在重叠,则返回包含具体路径的字符串字面量类型,由于我们期望最终类型为
void,TypeScript会抛出包含该错误信息的编译提示。
- 若
内容的提问来源于stack exchange,提问作者Lesiak
相关产品推荐
相关产品推荐

