一起聊聊 TypeScript 中的实用类型(utility type)和转换类型

开发 前端
Record<K extends keyof any, T> 是 TypeScript 提供的一个实用类型(utility type),用于构造一个对象类型,其中键 K 的集合可以是任意类型(通常是字符串、数字或符号),对应的值类型为 T。

在学习 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 用法示例

  1. 创建一个简单的对象类型: 假设我们想要创建一个对象类型,键是字符串,值是数字:
type StringToNumberMap = Record<string, number>;


const example: StringToNumberMap = {
    a: 1,
    b: 2,
    c: 3
};
  1. 限制键的集合: 假设我们有一组特定的键,值的类型是布尔型:
type Options = "option1" | "option2" | "option3";
type OptionFlags = Record<Options, boolean>;


const example: OptionFlags = {
    option1: true,
    option2: false,
    option3: true
};
  1. 结合接口使用: 如果我们有一个接口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]

这些类型工具在类型操作和变换中非常有用,帮助开发者更灵活地处理和定义类型。

责任编辑:武晓燕 来源: DevWiki
相关推荐

2024-08-09 13:39:27

2024-09-26 07:29:19

2021-03-18 00:04:13

C# 类型数据

2024-05-29 12:53:30

2023-04-26 07:42:16

WebGL图元的类型

2022-12-06 08:12:11

Java关键字

2023-12-28 09:55:08

队列数据结构存储

2023-10-26 08:38:43

SQL排名平分分区

2023-05-31 08:42:02

管理产品技术项目

2022-04-07 11:43:24

UPnPDLNA协议

2022-10-08 00:00:05

SQL机制结构

2023-04-26 07:30:00

promptUI非结构化

2024-11-11 11:33:57

2023-08-04 08:20:56

DockerfileDocker工具

2023-08-10 08:28:46

网络编程通信

2022-05-24 08:21:16

数据安全API

2023-09-10 21:42:31

2023-09-21 08:16:56

JDK 21向量计算计算

2023-06-30 08:18:51

敏捷开发模式

2024-03-04 08:45:30

JavaScript深度拷贝对象
点赞
收藏

51CTO技术栈公众号