Featured image of post TypeScript 实用程序类型:包含真实示例的完整指南Featured image of post TypeScript 实用程序类型:包含真实示例的完整指南

TypeScript 实用程序类型:包含真实示例的完整指南

TypeScript 实用程序类型的完整指南以及真实示例。涵盖部分、必需、选择、省略、提取、排除、记录、非空、参数等。

TypeScript 提供了一组丰富的内置实用程序类型,可以转换和操作其他类型。了解这些工具可以让您编写更具表现力和类型安全的代码,而无需重新发明轮子。

属性修改类型

这些类型修改对象属性的可选性、可变性和要求:

interface User {
  id: number;
  name: string;
  email?: string;
}

type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; }

type RequiredUser = Required<User>;
// { id: number; name: string; email: string; }

type ImmutableUser = Readonly<User>;
// { readonly id: number; readonly name: string; readonly email?: string; }
类型效果常见用途
占位符_0所有属性可选PATCH 请求机构
占位符_0所需的所有属性表单提交验证
占位符_0所有属性均为只读配置对象

Partial 对于 API 更新操作特别有用,其中客户端应该能够发送字段的子集:

async function updateUser(id: number, changes: Partial<User>): Promise<User> {
  const res = await fetch(`/api/users/${id}`, {
    method: 'PATCH',
    body: JSON.stringify(changes),
  });
  return res.json();
}

房产选择类型

PickOmit 允许从类型中选择或排除特定属性:

type UserView = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }

type UserWithoutEmail = Omit<User, 'email'>;
// { id: number; name: string; }

Omit 非常适合删除敏感字段:

type SafeUser = Omit<User, 'password' | 'token'>;

这些类型与交集类型很好地结合在一起,以实现细粒度控制:

type UserProfile = Pick<User, 'name' | 'email'> & { bio?: string };

联合过滤类型

ExtractExclude 根据类型兼容性过滤联合成员:

type Status = 'idle' | 'loading' | 'success' | 'error';
type ActiveStatus = Exclude<Status, 'idle'>;
// 'loading' | 'success' | 'error'

type ApiEvent =
  | { type: 'user.created'; user: User }
  | { type: 'user.deleted'; id: number }
  | { type: 'error'; message: string };

type UserEvents = Extract<ApiEvent, { type: `user.${string}` }>;
// { type: 'user.created'; user: User } | { type: 'user.deleted'; id: number }

NonNullable<T> 从类型中剥离 nullundefined

type Maybe = string | null | undefined;
type Definite = NonNullable<Maybe>; // string

对象构造类型

Record<K, T> 创建具有指定键和值类型的对象类型:

type UserMap = Record<string, User>;
type RolePermissions = Record<'admin' | 'editor' | 'viewer', string[]>;

const permissions: RolePermissions = {
  admin: ['create', 'read', 'update', 'delete'],
  editor: ['create', 'read', 'update'],
  viewer: ['read'],
};

函数和类类型

这些类型从函数签名中提取信息:

type Fn = (a: string, b: number) => boolean;

type Params = Parameters<Fn>;    // [string, number]
type Ret = ReturnType<Fn>;       // boolean
type FirstParam = Params[0];     // string

Awaited<T> 递归地解开 Promise 类型:

type AsyncResult = Awaited<Promise<Promise<string>>>; // string

InstanceType<T> 从构造函数中提取实例类型:

class Service { /* ... */ }
type ServiceInstance = InstanceType<typeof Service>; // Service

构图模式

组合实用程序类型可创建富有表现力的类型定义:

type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type UserUpdate = Optional<User, 'email'>;
// id and name required, email optional

对于深层部分对象,递归映射类型可以完成这项工作:

type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

掌握 TypeScript 实用程序类型可以减少样板代码,提高类型安全性,并使代码更具表现力。从 PartialPickRecord 开始,然后随着类型级编程需求的增长逐渐合并更高级的类型。