0Pricing
TypeScript Academy · 课时

插值的类型安全

从字符串中提取并要求相应的插值变量。

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

类型安全的插值

消息通常包含 "Hello, {name}" 这样的占位符。类型安全的国际化会从消息字符串类型中提取这些占位符名称,并要求您传入匹配的参数。

目标

给定消息的字面量类型,我们希望计算出它所需的变量对象,从而强制要求 t("greet", { name: "Ada" }),缺少 name 就会产生编译错误。

提取一个占位符

模板字面量条件类型会从只包含一个占位符的字符串中提取变量名称。在实际代码中,该模式用反引号写成:字符串、左花括号、infer V、右花括号、字符串。下面用 BraceMatch 表示这个匹配器。

// Real TS pattern (backtick template literal):
//   matches any text, then {V}, then any text; infers V.

type Var<S extends string> =
  S extends BraceMatch<infer V> ? V : never;

type A = Var<"Hello, {name}">; // "name"

提取多个占位符

通过递归将每个占位符收集到联合类型中。该模式会捕获一个变量和剩余的尾部,然后对尾部递归处理。

// Pattern: any text, {V}, then Rest tail -- infer V and Rest.

type Vars<S extends string> =
  S extends BraceMatchRest<infer V, infer Rest>
    ? V | Vars<Rest>
    : never;

type B = Vars<"Hi {first} {last}!">; // "first" | "last"

从名称转换为参数对象

使用映射类型,将名称联合类型转换为必需的对象类型。

type ArgsOf<S extends string> = {
  [K in Vars<S>]: string | number;
};

type G = ArgsOf<"Hello, {name}">;
// { name: string | number }

没有占位符就没有参数

当消息不包含占位符时,Vars 为 never,因此参数对象为空。此时可以让参数变为可选。

type C = Vars<"Goodbye">;       // never
type D = ArgsOf<"Goodbye">;     // {} (empty)

带类型的翻译函数

通过查找所选键对应的消息字面量并计算其参数,使参数取决于所选键。

declare const messages: {
  greet: "Hello, {name}";
  invite: "Join {count} others";
};

declare function t<K extends keyof typeof messages>(
  key: K,
  args: ArgsOf<(typeof messages)[K]>
): string;

实际执行约束

编译器现在会严格要求每条消息声明的确切变量。

t("greet", { name: "Ada" });   // ok
t("greet", {});                 // Error: name is missing
t("invite", { count: 3 });      // ok
t("invite", { name: "x" });     // Error: count missing, name unexpected

普通消息的可选参数

使用条件重载,这样不包含占位符的消息完全不需要第二个参数。

type MaybeArgs<S extends string> =
  Vars<S> extends never ? [] : [args: ArgsOf<S>];

declare function t2<K extends keyof typeof messages>(
  key: K,
  ...rest: MaybeArgs<(typeof messages)[K]>
): string;

自定义分隔符

如果您的目录使用 {{name}} 或 %{name},请相应调整 Vars 中的模板字面量模式。技术相同,只有外围字面量发生变化。

为何重要

缺失或拼写错误的插值变量是导致界面字符串损坏("Hello, undefined")的常见原因。在类型层面提取它们,可以将这类问题转化为编译错误,并记录每条消息的契约。

快速检查

测试您对插值类型安全的理解。

回顾

通过使用模板字面量对消息的字面量类型进行模式匹配,并结合infer,您可以将占位符名称提取为联合类型,将它们映射为必需的参数对象,并让翻译函数准确要求这些变量;如果没有变量,参数则可以省略。

常见问题解答

「插值的类型安全」课时是免费的吗?

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

「插值的类型安全」这节课中我会学到什么?

从字符串中提取并要求相应的插值变量。 你通过在浏览器中直接运行的动手代码来练习 TypeScript Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 TypeScript Academy 需要有经验吗?

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

「插值的类型安全」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. 翻译键的类型标注
  2. 插值的类型安全
  3. 使用类型处理复数形式
  4. 区域设置感知的类型推断
← 返回 TypeScript Academy