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 组合后,就能把取值范围约束得清清楚楚,是写出严谨类型的基础砖块。

笔记加载中…