高级类型工具

TypeScript 提供了一系列内置高级类型工具,可通过泛型参数灵活处理类型转换与提取。本章将以"工具手册"形式详解常用工具的使用方法,并通过实际案例演示组合应用,最后引导实现自定义类型工具。

Partial

作用:将泛型参数 T 中的所有属性转换为可选属性。
语法type Partial<T> = { [P in keyof T]?: T[P] }(TypeScript 内置实现)。
示例
定义用户接口 User 后,通过 Partial<User> 生成所有属性可选的类型:

typescript
复制代码
interface User {
  name: string;
  age: number;
  email: string;
}

// 所有属性变为可选:{ name?: string; age?: number; email?: string }
type PartialUser = Partial<User>;

应用:主要用于表单更新场景。当用户提交部分字段修改时(如仅更新姓名或年龄),无需传递完整对象,提升接口灵活性。

注意Partial<T> 仅对对象的直接属性生效,若属性值为嵌套对象,嵌套对象的属性不会自动变为可选。如需深度可选,需实现递归版本的 DeepPartial<T>

Pick<T, K>

作用:从泛型参数 T 中提取指定属性 KK 必须为 T 的属性键集合),生成仅包含这些属性的新类型。
语法type Pick<T, K extends keyof T> = { [P in K]: T[P] }(TypeScript 内置实现)。
示例
User 接口中仅提取 nameage 属性:

typescript
复制代码
// 仅包含 name 和 age:{ name: string; age: number }
type UserNameAge = Pick<User, 'name' | 'age'>;

应用:适用于API 响应数据过滤。后端返回数据可能包含冗余字段,通过 Pick 可精确筛选前端所需字段,减少数据传输量并提升类型安全性。

组合使用:Partial 与 Pick 的协同

单独使用高级类型工具可满足基础需求,而组合使用能解决更复杂场景。例如,通过 Partial<Pick<T, K>> 可实现"从 T 中选取部分属性并将其变为可选"的效果。

案例:用户信息编辑 API
假设需要设计一个用户信息编辑接口,要求:

  • 请求参数:允许用户修改部分信息(如姓名、年龄),但无需传递所有字段(可选);
  • 响应数据:仅返回用户 ID、修改后的姓名和年龄(精简字段)。

可通过以下类型设计实现:

typescript
复制代码
// 1. 定义基础用户类型
interface User {
  id: number;
  name: string;
  age: number;
  email: string;
  createdAt: Date; // 无需前端修改的字段
}

// 2. 请求参数类型:可选修改 name 和 age
type UpdateUserRequest = Partial<Pick<User, 'name' | 'age'>>;
// 等价于:{ name?: string; age?: number }

// 3. 响应类型:仅返回必要字段
type UpdateUserResponse = Pick<User, 'id' | 'name' | 'age'>;
// 等价于:{ id: number; name: string; age: number }

效果

  • 请求时,前端可仅传递 { name: "新名称" }{ age: 25 },接口仍能正常处理;
  • 响应时,仅返回 idnameage,避免暴露 emailcreatedAt 等敏感或冗余信息。

练习:实现自定义类型工具 ExcludeNull

目标:创建类型工具 ExcludeNull<T>,移除联合类型 T 中的 null 类型。

思路:使用 TypeScript 条件类型 T extends null ? never : T,若 Tnull 则返回 never(表示排除该类型),否则保留原类型。

实现代码

typescript
复制代码
type ExcludeNull<T> = T extends null ? never : T;

// 测试用例
type Test1 = ExcludeNull<string | number | null>; // 结果:string | number
type Test2 = ExcludeNull<boolean | null | undefined>; // 结果:boolean | undefined
type Test3 = ExcludeNull<null>; // 结果:never(无有效类型)

说明ExcludeNull 可用于净化可能包含 null 的数据类型,例如处理后端返回的可能为 null 的字段,确保前端使用时类型更安全。