概述

TypeScript 提供了一组强大的内置工具类型,旨在帮助开发者进行常见的类型转换和操作。这些工具类型极大地增强了 TypeScript 的类型系统,使得开发者能够编写更灵活和类型安全的代码。本文将详细介绍 TypeScript 的内置工具类型,并通过示例代码说明每个工具类型的使用方法和应用场景。

常用的内置工具类型

Partial<T>

Partial<T> 类型将对象类型 T 的所有属性变为可选。

示例

  1. interface User {
  2. id: number;
  3. name: string;
  4. email: string;
  5. }
  6. type PartialUser = Partial<User>;
  7. let user: PartialUser = {
  8. name: "Alice"
  9. };

使用场景

  • 配置对象:当函数或类的配置对象中,某些属性是可选时。
  • 数据更新:当部分更新对象的某些属性时,可以避免定义完整的对象结构。
  1. function updateUser(userId: number, update: Partial<User>) {
  2. // 只更新提供的属性
  3. console.log(`Updating user ${userId} with`, update);
  4. }
  5. updateUser(1, { name: "Alice" });

Required<T>

Required<T> 类型将对象类型 T 的所有属性变为必选。

示例

  1. interface User {
  2. id?: number;
  3. name?: string;
  4. email?: string;
  5. }
  6. type RequiredUser = Required<User>;
  7. let user: RequiredUser = {
  8. id: 1,
  9. name: "Alice",
  10. email: "alice@example.com"
  11. };

使用场景

  • 表单验证:当表单中的所有字段都是必填时,使用 Required 确保所有字段都被填充。
  • API 响应:当确保 API 响应中所有属性都存在时。
  1. function createUser(user: Required<User>) {
  2. // 确保所有属性都存在
  3. console.log("Creating user with", user);
  4. }
  5. createUser({ id: 1, name: "Alice", email: "alice@example.com" });

Readonly<T>

Readonly<T> 类型将对象类型 T 的所有属性变为只读。

示例

  1. interface User {
  2. id: number;
  3. name: string;
  4. email: string;
  5. }
  6. type ReadonlyUser = Readonly<User>;
  7. let user: ReadonlyUser = {
  8. id: 1,
  9. name: "Alice",
  10. email: "alice@example.com"
  11. };
  12. // user.id = 2; // Error: Cannot assign to 'id' because it is a read-only property.

使用场景

  • 防止修改:当不希望对象属性被修改时,使用 Readonly 确保对象的不可变性。
  • 常量定义:用于定义常量对象,使其属性不可变。
  1. const userConfig: Readonly<User> = {
  2. id: 1,
  3. name: "Alice",
  4. email: "alice@example.com"
  5. };
  6. // userConfig.name = "Bob"; // Error: Cannot assign to 'name' because it is a read-only property.

Pick<T, K>

Pick<T, K> 类型从对象类型 T 中选择一组属性 K,创建新的子类型。

示例

  1. interface User {
  2. id: number;
  3. name: string;
  4. email: string;
  5. }
  6. type UserContactInfo = Pick<User, "name" | "email">;
  7. let contactInfo: UserContactInfo = {
  8. name: "Alice",
  9. email: "alice@example.com"
  10. };

使用场景

  • 选择特定属性:当只需要某个类型中的部分属性时,使用 Pick 提取所需属性。
  • 数据传输:在网络请求或响应中,只传递必要的数据字段。
  1. function getUserContactInfo(user: User): UserContactInfo {
  2. return {
  3. name: user.name,
  4. email: user.email
  5. };
  6. }
  7. let contactInfo = getUserContactInfo({ id: 1, name: "Alice", email: "alice@example.com" });
  8. console.log(contactInfo); // { name: "Alice", email: "alice@example.com" }

Record<K, T>

Record<K, T> 类型创建一个新的对象类型,其中键是 K 的成员,值是 T 类型。

示例

  1. type Role = "admin" | "user" | "guest";
  2. type Permissions = Record<Role, string[]>;
  3. let permissions: Permissions = {
  4. admin: ["read", "write", "delete"],
  5. user: ["read", "write"],
  6. guest: ["read"]
  7. };

使用场景

  • 键值对映射:当需要定义键值对结构时,使用 Record 创建类型安全的映射对象。
  • 配置对象:用于定义具有固定键的配置对象。
  1. interface Config {
  2. setting: string;
  3. value: any;
  4. }
  5. type ConfigMap = Record<string, Config>;
  6. let configMap: ConfigMap = {
  7. featureA: { setting: "enabled", value: true },
  8. featureB: { setting: "timeout", value: 3000 }
  9. };

Exclude<T, U>

Exclude<T, U> 类型从类型 T 中排除所有可以赋值给类型 U 的类型。

示例

  1. type Primitive = string | number | boolean;
  2. type NonString = Exclude<Primitive, string>; // number | boolean

使用场景

  • 类型过滤:当需要从联合类型中排除某些类型时,使用 Exclude 进行过滤。
  • 类型优化:移除不需要的类型,以优化类型定义。
  1. type AllowedTypes = Exclude<string | number | (() => void), Function>; // string | number

Extract<T, U>

Extract<T, U> 类型从类型 T 中提取所有可以赋值给类型 U 的类型。

示例

  1. type Primitive = string | number | boolean;
  2. type StringOrNumber = Extract<Primitive, string | number>; // string | number

使用场景

  • 类型选择:当需要从联合类型中提取某些类型时,使用 Extract 进行选择。
  • 类型定义:定义只包含特定类型的联合类型。
  1. type FunctionTypes = Extract<string | number | (() => void), Function>; // () => void

NonNullable<T>

NonNullable<T> 类型移除类型 T 中的 nullundefined

示例

  1. type NullableString = string | null | undefined;
  2. type NonNullString = NonNullable<NullableString>; // string

使用场景

  • 类型约束:当需要移除类型中的 nullundefined 以确保类型安全时,使用 NonNullable 进行约束。
  • 类型优化:移除不必要的 nullundefined 类型,以优化类型定义。
  1. function processValue(value: NonNullable<string>) {
  2. console.log("Processing:", value);
  3. }
  4. // processValue(null); // Error: Argument of type 'null' is not assignable to parameter of type 'string'.
  5. processValue("Hello"); // Processing: Hello

ReturnType<T>

ReturnType<T> 类型获取函数类型 T 的返回类型。

示例

  1. function exampleFunction() {
  2. return { name: "Alice", age: 25 };
  3. }
  4. type ExampleReturnType = ReturnType<typeof exampleFunction>; // { name: string; age: number }

使用场景

  • 类型推断:当需要推断函数的返回类型时,使用 ReturnType 获取返回类型。
  • 类型重用:在多个地方使用相同的返回类型定义,以提高代码的可重用性。
  1. function createUser() {
  2. return { id: 1, name: "Alice" };
  3. }
  4. type UserType = ReturnType<typeof createUser>;
  5. function printUser(user: UserType) {
  6. console.log("User:", user);
  7. }
  8. printUser(createUser()); // User: { id: 1, name: 'Alice' }

InstanceType<T>

InstanceType<T> 类型获取构造函数类型 T 的实例类型。

示例

  1. class ExampleClass {
  2. constructor(public name: string, public age: number) {}
  3. }
  4. type ExampleInstance = InstanceType<typeof ExampleClass>; // ExampleClass

使用场景

  • 类型推断:当需要推断类的实例类型时,使用 InstanceType 获取实例类型。
  • 类型重用:在多个地方使用相同的实例类型定义,以提高代码的可重用性。
  1. class User {
  2. constructor(public id: number, public name: string) {}
  3. }
  4. type UserInstance = InstanceType<typeof User>;
  5. function printUserInstance(user: UserInstance) {
  6. console.log("User:", user);
  7. }
  8. const user = new User(1, "Alice");
  9. printUserInstance(user); // User: User { id: 1, name: 'Alice'
  10. }

结论

内置工具类型是 TypeScript 类型系统中的重要组成部分,它们提供了灵活且强大的类型转换和操作方式。通过掌握这些内置工具类型,你可以编写出更具通用性和可重用性的代码。在实际开发中,合理使用这些工具类型可以提高代码的类型安全性和可读性,帮助你更好地处理复杂的数据结构和类型操作。