TypeScript 提取值做为字面量

5 阅读2分钟

在 TypeScript 中,如果你想以对象的值做为字面量类型,核心方法是使用 as const 配合索引访问类型。

这通常分为两个步骤:

  1. 锁定对象的值:使用 as const 告诉 TypeScript 不要将对象的值推断为宽泛的类型(如 stringnumber),而是推断为具体的字面量(如 "admin"1)。
  2. 提取值的类型:使用 typeof 获取对象类型,再用索引语法 [key]keyof typeof 提取具体的值类型。

以下是几种常见的写法和场景:

1. 基础写法:对象值转联合类型

假设你有一个配置对象,你想把它的值变成类型:

// 定义一个常量对象,并用 as const 锁定其值的类型
const Roles = {
  ADMIN: "admin",
  USER: "user",
  GUEST: "guest"
} as const;

// 提取值作为类型 (等同于 type Role = "admin" | "user" | "guest")
type Role = typeof Roles[keyof typeof Roles];

// 使用
const userRole: Role = Roles.ADMIN; // ✅ 正确
const invalid: Role = "super";      // ❌ 错误:类型不匹配

2. 提取特定键的值

如果你只想提取某个特定属性的字面量类型:

const Status = {
  SUCCESS: 200,
  ERROR: 500,
  PENDING: 100
} as const;

// 只提取 SUCCESS 的值类型 (即字面量类型 200)
type SuccessCode = typeof Status["SUCCESS"];

const code: SuccessCode = 200; // ✅ 只能是 200

3. 数组值转字面量类型

对于数组,as const 会将其推断为只读元组,你可以提取数组元素的联合类型:

// 字符串数组
const COLORS = ["red", "green", "blue"] as const;

// 提取类型:等同于 "red" | "green" | "blue"
type Color = typeof COLORS[number];

let myColor: Color = "red";   // ✅
myColor = "yellow";           // ❌ 错误

4. 为什么需要 as const

如果不使用 as const,TypeScript 的类型推断机制会默认将变量推断为宽泛的类型(如 string),导致你无法精确获取字面量。

写法推断的类型能否作为字面量类型使用
const obj = { role: "admin" }{ role: string }❌ 否 (变成了 string)
const obj = { role: "admin" } as const{ readonly role: "admin" }✅ 是 (精确的字面量)