Record 是 TypeScript 提供的一个工具类型(Utility Type),它用来快速构造一个对象类型,其中的 键和值的类型都可以指定。
定义
ts
Record<Keys, Type>
-
Keys: 一组属性键,可以是联合类型(string、number、symbol,或者它们的联合)。
-
Type: 每个键对应的属性值的类型。
作用
相当于生成:
ts
{
[K in Keys]: Type
}
示例
基本用法
ts
type UserRole = "admin" | "user" | "guest";
// 构造一个类型,key 是 UserRole,值是 string
type RoleDescriptions = Record<UserRole, string>;
const roleDesc: RoleDescriptions = {
admin: "Has full access",
user: "Regular user",
guest: "Read-only access"
};
这里 roleDesc 必须包含 "admin" | "user" | "guest" 三个键,而且值必须是 string。
限制键的范围
ts
type Status = "success" | "error" | "loading";
const statusColors: Record<Status, string> = {
success: "green",
error: "red",
loading: "gray"
};
如果少写一个键,或者写错,会编译报错。
用于对象映射
ts
interface User {
id: number;
name: string;
}
type UserMap = Record<number, User>;
const users: UserMap = {
1: { id: 1, name: "Alice" },
2: { id: 2, name: "Bob" }
};
这里相当于一个 id -> User 的映射。
对比
-
Record<Keys, Type>等价于:ts{ [K in Keys]: Type } -
Partial<Record<Keys, Type>>可以让这些键变为可选。
Record vs Map vs 索引签名
| 特性 | Record<Keys, Type> | Map<Key, Value> | 索引签名 { [key: string]: Type } |
|---|---|---|---|
| 定义位置 | 类型层面:构造对象类型 | 运行时数据结构:ES6 Map | 类型层面:对象的属性约束 |
| 键的范围 | 必须是 已知联合类型 或基本类型 (`string | number | symbol`) |
| 值的类型 | 必须统一为 Type | 任意值 | 必须统一为 Type |
| 是否强制所有键都出现 | 是的(除非用 Partial<Record<...>>) | 否,可以动态增删 | 否,对象可选地添加键 |
| 运行时表现 | 只是个 静态类型约束,编译后消失 | 真实的数据结构,方法丰富(.set(), .get(), .has()) | 普通对象(JS 对象) |
| 适用场景 | 静态定义键值映射(例如 status -> color,role -> permission) | 动态键值存储,需要高效查找、非字符串键 | 需要灵活的对象键,键集合不固定 |
举例对比
Record
ts
type Status = "success" | "error" | "loading";
const statusColors: Record<Status, string> = {
success: "green",
error: "red",
loading: "gray"
};
// ✅ 编译时就能发现漏写/拼写错误
Map
ts
const userMap = new Map<number, string>();
userMap.set(1, "Alice");
userMap.set(2, "Bob");
// ✅ 键可以是对象
const objKey = {};
userMap.set(objKey, "value");
索引签名
ts
const dict: { [key: string]: number } = {};
dict["a"] = 1;
dict["b"] = 2;
// ✅ 键集合完全自由,不做限制
👉 总结一下:
-
你知道键的全集 → 用
Record(最安全,编译期就能发现错误)。 -
需要运行时动态键值对(特别是对象做 key)→ 用
Map。 -
只想随便存键值,不在意遗漏/拼写错误 → 用 索引签名。