在学习 TypeScript 中遇到了Record 这个类型, 一开始不知道其用途, 查找了一下说明才得知:
Record<K extends keyof any, T> 是 TypeScript 提供的一个实用类型(utility type),用于构造一个对象类型,其中键 K 的集合可以是任意类型(通常是字符串、数字或符号),对应的值类型为 T。
1. 详细解释
1.1 定义
Record<K extends keyof any, T> 的定义如下:
type Record<K extends keyof any, T> = {
[P in K]: T;
};
- K extends keyof any:表示 K 可以是任何合法的键类型。keyof any 是 TypeScript 中的一个特殊类型,它等价于 string | number | symbol。
- T:表示属性的值的类型。
- { [P in K]: T; }:这是一种映射类型语法,表示生成一个对象类型,这个对象的键是 K 中的每一个键,其对应的值类型都是 T。
1.2 用法示例
- 创建一个简单的对象类型: 假设我们想要创建一个对象类型,键是字符串,值是数字:
type StringToNumberMap = Record<string, number>;
const example: StringToNumberMap = {
a: 1,
b: 2,
c: 3
};
- 限制键的集合: 假设我们有一组特定的键,值的类型是布尔型:
type Options = "option1" | "option2" | "option3";
type OptionFlags = Record<Options, boolean>;
const example: OptionFlags = {
option1: true,
option2: false,
option3: true
};
- 结合接口使用: 如果我们有一个接口Person,我们想要创建一个包含多个Person对象的记录:
interface Person {
name: string;
age: number;
}
type PersonDictionary = Record<string, Person>;
const persons: PersonDictionary = {
john: { name: "John Doe", age: 25 },
jane: { name: "Jane Smith", age: 30 }
};
1.3 详细示例
假设我们需要管理一组用户,每个用户都有一个唯一的标识符(ID)。我们可以使用 Record 来定义一个用户字典:
interface User {
id: number;
name: string;
email: string;
}
type UserDictionary = Record<number, User>;
const users: UserDictionary = {
1: { id: 1, name: "John Doe", email: "john.doe@example.com" },
2: { id: 2, name: "Jane Smith", email: "jane.smith@example.com" },
3: { id: 3, name: "Emily Johnson", email: "emily.johnson@example.com" }
};
// 访问用户信息
console.log(users[1].name); // 输出: John Doe
在这个示例中:
- User 接口定义了用户对象的结构。
- UserDictionary 使用 Record<number, User> 创建了一个类型,该类型的键是数字,值是 User 类型。
- users 变量是一个 UserDictionary 类型的对象,包含多个用户条目。
2. 类型工具
Record<K extends keyof any, T> 类型在 TypeScript 中非常有用,可以用来定义一个键和值类型的映射。它允许我们动态地创建具有特定键集合和值类型的对象类型,广泛应用于需要键值对数据结构的场景。
在 TypeScript 中还有不少类似的类型工具用于操作和转换类型。以下是它们的具体区别和用途:
- Partial
作用:将类型 T 的所有属性变为可选。
用法:
interface Person {
name: string;
age: number;
}
type PartialPerson = Partial<Person>;
// Equivalent to: { name?: string; age?: number; }
- Required
作用:将类型 T 的所有属性变为必需。
用法:
interface Person {
name?: string;
age?: number;
}
type RequiredPerson = Required<Person>;
// Equivalent to: { name: string; age: number; }
- Readonly
作用:将类型 T 的所有属性变为只读。
用法:
interface Person {
name: string;
age: number;
}
type ReadonlyPerson = Readonly<Person>;
// Equivalent to: { readonly name: string; readonly age: number; }
- Pick<T, K extends keyof T>
作用:从类型 T 中挑选一组属性 K 组成新的类型。
用法:
interface Person {
name: string;
age: number;
address: string;
}
type PersonNameAndAge = Pick<Person, 'name' | 'age'>;
// Equivalent to: { name: string; age: number; }
- Record<K extends keyof any, T>
作用:构建一个类型,其键为 K 类型,值为 T 类型。
用法:
type PersonRecord = Record<string, number>;
// Equivalent to: { [key: string]: number; }
- Exclude<T, U>
作用:从类型 T 中排除可以赋值给 U 的类型。
用法:
type T = string | number | boolean;
type Excluded = Exclude<T, boolean>;
// Equivalent to: string | number
- Extract<T, U>
作用:从类型 T 中提取可以赋值给 U 的类型。
用法:
type T = string | number | boolean;
type Extracted = Extract<T, boolean>;
// Equivalent to: boolean
- Omit<T, K extends keyof any>
作用:构建一个类型,其具有类型 T 的属性,除了那些在 K 中的属性。
用法:
interface Person {
name: string;
age: number;
address: string;
}
type PersonWithoutAddress = Omit<Person, 'address'>;
// Equivalent to: { name: string; age: number; }
- NonNullable
作用:从类型 T 中排除 null 和 undefined。
用法:
type T = string | number | null | undefined;
type NonNullableT = NonNullable<T>;
// Equivalent to: string | number
- Parameters<T extends (...args: any) => any>
作用:获取函数类型 T 的参数类型组成的元组。
用法:
type Func = (a: string, b: number) => void;
type Params = Parameters<Func>;
// Equivalent to: [string, number]
这些类型工具在类型操作和变换中非常有用,帮助开发者更灵活地处理和定义类型。