0Pricing
TypeScript Academy · 课时

类型级 DSL 中的错误消息

向 DSL 用户展示有帮助的编译错误。

类型级 DSL 中的错误消息 是 CoddyKit 上的免费 TypeScript Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 TypeScript Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 TypeScript Academy 课程共包含 4 节课。

类型级 DSL 中的易读错误

类型级 DSL 最困难的部分,是让失败信息易于理解。原始的 never 或“不可赋值”错误会让用户困惑。我们通过品牌化错误类型和精心设计的 never 消息,提供描述性错误。

never 类型的问题

当验证失败并解析为 never 时,编译器会说“类型 X 的参数无法赋给 never”,却不会告诉用户原因。我们可以做得更好。

品牌化错误类型

不要返回普通的 never,而应返回一种形状独特的错误类型,并在其类型中携带人类可读的消息字符串。

type TypeError<Msg extends string> = {
  readonly __error: Msg;
};

type E = TypeError<"Column 'foo' does not exist">;

从验证中返回错误

验证器会返回有效值类型,或返回描述问题的品牌化错误。“包含点号”的检查是一个模板字面量模式(实际代码中使用反引号);这里将其记作 HasDot。

// HasDot<S> is the backtick pattern: any text, ".", any text.

type Validate<S extends string> =
  S extends HasDot
    ? S
    : TypeError<"Path must contain a dot, e.g. user.name">;

强制显示错误

请约束参数,使传入的任何内容都不能赋给错误品牌类型,从而显示该消息。错误类型会直接出现在编译器输出中。

declare function path<S extends string>(
  p: Validate<S> extends TypeError<infer M> ? TypeError<M> : S
): void;

path("oops");
// Error message includes: __error: "Path must contain a dot..."

区分多个错误

不同的失败会返回不同的消息,因此用户可以获得具体指导,而不是面对一种通用拒绝。HasDot 仍然是表示“包含点号”的反引号模板字面量模式。

type Check<S extends string> =
  S extends "" ? TypeError<"Path cannot be empty">
  : S extends HasDot ? S
  : TypeError<"Missing dot separator">;

never 类型的巧妙用法

另一种技术是将值位置与字面量消息配对,以便悬停查看时显示该消息。您可以将出错类型与带标签的对象进行交集组合。

type Invalid<M extends string> = { error: M } & never;
// using never keeps it unassignable while the label hints the cause

流式 DSL 中的错误

在链式 DSL 中,请让无效的下一步返回品牌化错误类型,而不是有效阶段,这样编辑器就会在错误发生的位置显示消息。

interface Stage {
  // calling done() before where() yields a labeled error
  done(): TypeError<"Call .where() before .done()">;
}

保持消息简短

过长的消息类型会使编译器输出膨胀,并拖慢工具运行。请优先使用简洁且可执行的短语。如果代价很低,可以包含出错的令牌,但请避免巨大的插值内容。

测试错误

请编写类型级测试,断言已知错误输入会出现错误品牌,这样重构就不会在不知不觉中损害开发者体验。

type Expect<T extends true> = T;
type _t = Expect<Validate<"oops"> extends TypeError<any> ? true : false>;

为何重要

DSL 的质量取决于其错误信息。品牌化错误类型可以将晦涩的 never 失败转化为自解释的消息,从而显著改善使用类型级接口时的体验。

快速检查

请确认您对类型级错误消息的理解。

回顾

为了让类型级 DSL 易于使用,请用包含易读消息的品牌化错误类型替代单独的 never。验证器会返回有效类型或特定的错误品牌;约束参数可以让消息显示在编译器输出中。请保持消息简短,并对其进行测试。

常见问题解答

「类型级 DSL 中的错误消息」课时是免费的吗?

是的 — 「类型级 DSL 中的错误消息」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 TypeScript Academy 课程的其余内容,请升级到 CoddyKit PRO。 TypeScript Academy 课程共包含 4 节课。

「类型级 DSL 中的错误消息」这节课中我会学到什么?

向 DSL 用户展示有帮助的编译错误。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 TypeScript Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「类型级 DSL 中的错误消息」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 TypeScript Academy 课中编写并运行代码吗?

能。每节 TypeScript Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 什么是类型级 DSL
  2. 设计流式查询 DSL
  3. 编译时输入验证
  4. 类型级 DSL 中的错误消息
← 返回 TypeScript Academy