TypeScript 如何定义字面量类型
你有没有遇到过这种情况:写代码时明明只允许用“周一”到“周日”这7个字符串,结果不小心写成了“星期八”,编译器还查不出来?或者想让函数参数只能传“开启”或“关闭”,结果传了个“待机”,运行时才报错?这时候TypeScript的“字面量类型”就能帮上大忙——它不是要你学复杂的新概念,反而像给代码设了个“精准门禁”,只允许特定的“小范围值”通过,从根源减少低级错误。
什么是字面量类型?就像给值“定死范围”
字面量类型,简单说就是把某个具体的值直接当成“类型”来用。和普通的字符串、数字类型不同,它不允许随便填值,只能用你指定的那几个。

举个生活化的例子:你家小区的快递柜,只能用小区发的取件码开门,不能用随便一串数字。这个“小区取件码”就类似字面量类型——它不是“所有数字”,而是“某一串特定数字”。
再用代码说清楚:如果用普通的字符串类型定义状态,你可以随便写任何字符串,比如:
`typescript
let status: string;
status = "开启"; // 没问题
status = "待机"; // 编译也不报错,运行时才出问题
`
但如果用字面量类型,把状态限定死只能是“开启”或“关闭”,写“待机”就会直接报错:
`typescript
let status: "开启" | "关闭";
status = "开启"; // 正确
status = "关闭"; // 正确
status = "待机"; // 报错!不符合要求的类型
`
用联合类型:给一个值设多个可选范围
刚才的例子里,只能选两个值中的一个,这就是“联合类型”——用|符号把多个字面量类型连起来,意思是“满足其中任意一个就行”。它就像奶茶店的“可选糖度”,只能选“三分糖”“五分糖”“全糖”,不能选其他的。
再举个实用的场景:做网页的主题切换,主题只能是“light”(浅色)、“dark”(深色)、“auto”(自动)这三个。如果不用字面量类型,用string的话,不小心写错成“drak”,运行时页面就会乱;用字面量类型的话,编辑器会直接提醒你“只有三个选项可选”:
`typescript
type Theme = "light" | "dark" | "auto";
let currentTheme: Theme;
currentTheme = "light"; // 正确
currentTheme = "dark"; // 正确
currentTheme = "drak"; // 报错!编译器提前拦住错误
`
这种提前纠错的能力,能帮你省掉很多调试的时间,不用等到用户反馈页面显示不对才改。
数字/布尔值也能当字面量类型,不止字符串
字面量类型不只是字符串,数字和布尔值也能用。比如做游戏的计分系统,要求得分只能是0、1、2,用数字字面量类型就不会出现“得分是3.5”这种不合理的情况:
`typescript
type Score = 0 | 1 | 2;
let gameScore: Score;
gameScore = 1; // 正确
gameScore = 3; // 报错,不符合计分规则
`
还有布尔值,比如控制某个按钮是否可见,要求只能是true或false,用字面量类型就不会出现“布尔值传了字符串‘是’”这种低级错误。
实际开发里的小技巧:用字面量类型简化代码
很多新手会把字面量类型直接写在变量里,比如let status: "开启" | "关闭",如果多处用到这个状态,每次都写一遍就很麻烦。这时候可以用type别名,把字面量联合类型存成一个新类型,之后直接用这个新类型就行:
`typescript
type Status = "开启" | "关闭"; // 把字面量类型存成别名
let doorStatus: Status; // 直接用
doorStatus = "开启"; // 正确
`
就像你给朋友起了个昵称,之后喊昵称比喊全名方便多了,这个别名就是简化重复代码的小工具。
可能有人会问,“这和直接写注释提醒有什么区别?”区别在于:注释是给人看的,编译器不会检查注释;而字面量类型是给编译器的规则,只要不符合要求,代码根本跑不起来,从根源上避免了人为的疏忽。
简单说,字面量类型就是TypeScript给代码加的“精准过滤网”,只留你指定的合法值,把错误挡在写代码的时候,而不是等到运行后。不管是做状态控制、参数校验还是规则限定,它都是让代码更严谨的实用小工具。