You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测对象重叠叶子节点并生成友好编译期错误提示

问题描述

我有两个不应存在共同叶子节点的对象:

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'.

错误信息直接包含了具体的重叠路径,完全符合需求。

原理说明

  1. Leaves<T>保持原有逻辑,负责递归生成所有叶子节点的字符串路径;
  2. Overlap通过交集类型提取两个路径集合的共同部分;
  3. ErrorIfOverlapping利用条件类型判断:
    • 若Overlap为never(无重叠),则返回void,无编译错误;
    • 若存在重叠,则返回包含具体路径的字符串字面量类型,由于我们期望最终类型为void,TypeScript会抛出包含该错误信息的编译提示。

内容的提问来源于stack exchange,提问作者Lesiak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:10:19