在 TypeScript 中,如果你想以对象的值做为字面量类型,核心方法是使用 as const 配合索引访问类型。
这通常分为两个步骤:
- 锁定对象的值:使用
as const告诉 TypeScript 不要将对象的值推断为宽泛的类型(如string或number),而是推断为具体的字面量(如"admin"或1)。 - 提取值的类型:使用
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" } | ✅ 是 (精确的字面量) |