Record
是 TypeScript 提供的一个内置工具类型,它允许你构建一个对象类型,映射特定的键到指定的值类型。它通过映射类型(Mapped Types)实现,能够有效地将一组特定的键映射到某个类型的值。Record
在实际开发中非常有用,尤其是当你需要定义某些固定键并确保每个键对应的值符合特定类型时。
Record
类型的基本语法
Record<K, T>;
在上面的代码中:
-
K
:表示对象的 键,它通常是一个字面量类型或者联合类型,也可以是string
、number
或symbol
等类型的集合。 -
T
:表示对象的 值,它是所有键对应的值的类型。
Record
类型的作用是将类型 K
中的每个键映射到类型 T
的值。换句话说,它会创建一个对象类型,其中每个属性的键来自 K
,每个属性的值都符合类型 T
。
假设你需要定义一个对象,表示某个应用中不同状态的数值代码,Record
可以帮助你创建这样的类型:
type Status = 'pending' | 'approved' | 'rejected';
const statusCodes: Record<Status, number> = {
pending: 0,
approved: 1,
rejected: 2,
};
在上面的代码中:
-
Status
是一个联合类型,包含'pending'
、'approved'
和'rejected'
。 -
Record<Status, number>
表示一个对象,其键为Status
类型中的每个值,值的类型是number
。 -
通过
Record
,我们确保了每个状态对应的值必须是数字。
Record
可以与其他类型工具结合使用,提供更强大的类型定义。例如,你可以结合 Partial
来构建一个对象,其中的键是必需的,但某些属性可能是可选的。
type User = 'admin' | 'editor' | 'viewer';
type UserPermissions = Record<User, boolean>;
const userPermissions: Partial<UserPermissions> = {
admin: true,
editor: false,
};
在这个例子中,Partial<UserPermissions>
表示 userPermissions
对象是 UserPermissions
类型的一个可选版本。也就是说,我们可以只部分定义某些角色的权限,而其他角色的权限则可以被省略。
你也可以使用 Record
来根据动态生成的键创建类型。例如,当你需要从一个列表生成一个对象,并为每个列表项赋值时,Record
可以帮助你保持类型的正确性。
const ids = ['id1', 'id2', 'id3'] as const;
type Id = (typeof ids)[number]; // 'id1' | 'id2' | 'id3'
const userInfo: Record<Id, { name: string; age: number }> = {
id1: { name: 'Alice', age: 30 },
id2: { name: 'Bob', age: 25 },
id3: { name: 'Charlie', age: 28 },
};
在这个例子中:
-
ids
是一个包含字符串字面量的数组,并通过as const
声明为一个常量数组,类型推导为'id1' | 'id2' | 'id3'
。 -
Record<Id, { name: string; age: number }>
定义了一个对象,键是id1
、id2
和id3
,值是一个包含name
和age
属性的对象。
Record 的实现原理
Record<K, T>
就是基于映射类型实现的。Record 类型接受两个参数:K
和 T
,其中 K
是键的类型,T
是值的类型。
type Record<K extends keyof any, T> = {
[P in K]: T;
};
在上面的代码中:
-
K extends keyof any
:表示 K 是一个可以作为对象键的类型,通常是 string、number 或 symbol。 -
[P in K]
: T:表示遍历 K 中的每一个键 P,并将它们的类型设置为 T。
总结
Record<K, T>
是通过映射类型实现的,它遍历类型 K 中的每一个键,并将每个键的值类型设为 T。这种实现方式允许你根据键的集合动态创建一个对象类型,并保证每个键的值符合特定的类型。Record 是 TypeScript 中非常实用的工具类型之一,常用于构建字典、映射和配置对象等。