TypeScript 字面量类型
字面量是代码中直接写出的值,例如字符串 "ok"、数字 42、布尔 true。字面量类型把「值本身」当作类型来用,让某个位置的取值只能是指定的那一个,从而把类型约束精确到具体值——这是普通 string/number 类型做不到的。
基础字面量类型
字符串、数字、布尔三种字面量都能直接作为类型标注:
const a: "hello" = "hello"; // 字符串字面量类型
const b: 42 = 42; // 数字字面量类型
const c: true = true; // 布尔字面量类型
// a = "hi"; // 报错:不能将类型 "hi" 赋给类型 "hello"
// b = 43; // 报错:不能将类型 43 赋给类型 42
单独使用意义不大,它最大的价值是配合联合类型约束取值范围。
联合字面量:轻量枚举
用 | 组合多个字面量,就能像枚举一样限定可选项:
type Direction = "up" | "down" | "left" | "right";
function move(dir: Direction): void {
console.log("方向:" + dir);
}
move("up"); // 输出:方向:up
// move("back"); // 报错:类型 "back" 不存在于 Direction
type Result = "success" | "failure" | 0 | 1; // 字符串与数字可混用
参数、返回值、配置项都适合用联合字面量表达「有限的选项」。
const 与 let 的推断差异
const 声明的值会推断为字面量类型,let 则被放宽为宽泛的基础类型:
const a = "left"; // a 的类型是 "left"
let b = "left"; // b 的类型是 string
let x: "left" = a; // 合法:a 就是字面量 "left"
// let y: "left" = b; // 报错:string 不能赋给 "left"
这就是为什么函数参数要求字面量类型时,传入 let 变量会类型不匹配,需要显式断言或改用 const 声明。
as const:把对象整体收窄
as const 断言让对象的所有属性都推断为字面量类型,并整体只读:
const config = {
env: "prod", // 不加 as const 会推断成 string
port: 8080
} as const;
// config.env = "dev"; // 报错:属性只读
type Env = typeof config.env; // type Env = "prod"
type Port = typeof config.port; // type Port = 8080
路由表、常量映射、配置对象常借助 as const 获得精确类型,再配合 keyof、映射类型派生新类型。
小结:字面量类型用「值」当「类型」,单独用价值不大;与联合类型、as const 组合后,就能把取值范围约束得清清楚楚,是写出严谨类型的基础砖块。