字面量类型 允许将变量的可能值限制为某些特定的常量,而不是简单的通用类型(例如,不只是数字,而是数字 5 或字符串 "yes")。
这在创建具有固定参数、状态等的 API 时非常有用。
type Direction = 'left' | 'right' | 'up' | 'down'; function move(dir: Direction) { // ... } move('left'); // 好 move('top'); // 编译错误!
它还适用于数字、布尔值甚至完整的结构(元组字面量类型):
type WeekDay = 1 | 2 | 3 | 4 | 5 | 6 | 7; const day: WeekDay = 6; // 好
const d = 'left'; // 类型为 'left' (字面量) let e = 'left'; // 类型为 string (普通)
问题: 如果将变量定义为 const x = "yes";,那么它会获得什么类型?之后能否将其他字符串值赋给它?
答案:
const x = "yes"; — x 的类型将是 "yes" (字面量类型),并且它不能被赋值为任何其他值,除了 'yes'(因为 const,根本无法更改)。let x = "yes";,则 x 将被类型为 string,可以赋值为任何字符串。const x = 'yes'; // x: 'yes' let y = 'yes'; // y: string
故事
在一个任务状态项目中使用了枚举,但开发人员用字符串替换了它。结果是,API 开始接受任何字符串作为状态,这在产品发展的过程中产生了许多错误,因为失去了控制。
故事
开发人员试图在数据验证中使用字面量类型,但直接将表单字段的参数赋值 — TS 允许这样做,因为输入字段的类型是字符串,而不是字面量(例如,"ok" | "fail"),因为输入值没有经过验证。最终在运行时出现了不在允许集合中的值。
故事
在为一个需要字面量值的函数编写测试时,自动生成的测试意外地提供了一个字符串参数,测试未通过。后来发现,由于在 let 声明时对类型输出的不注意,类型被放宽,编译器并没有捕捉到这个问题。