← 返回题目列表

TypeScript 模板字面量类型能解决什么问题?

中等 第 25 / 32 题 更新于 2026/07/29
TypeScript模板字面量类型类型编程

简化版

模板字面量类型可以在类型层面拼接字符串字面量,用来表达事件名、接口路径、CSS 变量名、状态 key 等有规律的字符串集合。

它常和联合类型、映射类型、条件类型配合,把一组基础字段转换成更具体的字符串类型,从而减少手写字符串和拼写错误。

详细版

type EventName = "click" | "change";
type HandlerName = `on${Capitalize<EventName>}`;
// "onClick" | "onChange"

用字段生成事件:

type Model = {
  name: string;
  age: number;
};

type ChangeEvent = `${keyof Model & string}Changed`;
// "nameChanged" | "ageChanged"

模板字面量类型不是运行时代码,它只在编译期约束字符串形状。字符串组合过多时会产生笛卡尔积,类型数量可能快速膨胀。

完整版教学

一、它解决的是“有规律字符串”的类型表达

很多前端字符串不是随便写的,而是有命名规则。

field name -> nameChanged
field age  -> ageChanged

模板字面量类型让这些规则在类型系统里表达出来。

它的价值不是炫技,而是把字符串约定从文档搬进编译器。

二、基础语法和运行时模板字符串相似

type Size = "sm" | "md" | "lg";
type ClassName = `button-${Size}`;

得到:

基础类型结果
"sm""button-sm"
"md""button-md"
"lg""button-lg"

这只发生在类型层,不会生成任何 JavaScript。

三、联合类型会展开成组合

type Method = "get" | "post";
type Resource = "User" | "Order";

type ApiName = `${Method}${Resource}`;
// "getUser" | "getOrder" | "postUser" | "postOrder"

如果两个联合分别有 10 个成员,组合后就是 100 个字符串。数量很大时要克制。

四、常和内置字符串工具类型配合

TypeScript 提供了 UppercaseLowercaseCapitalizeUncapitalize

type Field = "name" | "email";
type Setter = `set${Capitalize<Field>}`;
// "setName" | "setEmail"

这类组合适合生成事件名、setter 名、组件 prop 名等。

五、和映射类型配合生成 API

type Watchers<T> = {
  [K in keyof T & string as `${K}Changed`]: (value: T[K]) => void;
};

type UserWatchers = Watchers<{
  name: string;
  age: number;
}>;

这里 as 做键名重映射,模板字面量类型负责生成新键。

六、不要滥用到不可维护

模板字面量类型适合规则稳定的字符串集合,不适合把复杂业务协议全部写成类型体操。

type Path = `/api/${"user" | "order"}/${"list" | "detail"}`;

如果路径规则来自后端 OpenAPI,自动生成类型通常比手写复杂模板更可靠。

七、常见误区与追问

  • 误区:模板字面量类型会在运行时拼字符串。 它只存在于类型检查阶段。
  • 误区:模板字面量类型只能拼接两个字符串。 它可以组合多个占位类型。
  • 误区:联合组合没有成本。 多个大联合会产生大量组合类型。
  • 误区:它可以校验任意复杂字符串格式。 复杂格式更适合运行时校验或代码生成。
  • 追问:为什么要写 keyof T & string 因为对象键还可能是 number 或 symbol,模板字符串需要字符串类 key。
  • 追问:它和映射类型怎么配合? 通过键名重映射 as 生成新属性名。

八、加强记忆

记忆链路:

union -> template literal -> new string union
keyof  -> remap key       -> typed API surface

回答时先讲有规律字符串,再给事件名或 setter 名例子,最后提醒联合笛卡尔积和运行时校验边界。