返回

TypeScript Utility Types 学习笔记及源码解析

前端

TypeScript 工具类型学习笔记及源码解析

TypeScript 中的工具类型是一组内置的类型,可以用来创建新的类型。这些类型非常强大,可以用来解决各种各样的问题。

TypeScript 工具类型有以下几种:

  • Partial
  • Required
  • Readonly
  • Record
  • Pick
  • Omit
  • Exclude
  • NonNullable
  • Nullable
  • Parameters
  • Arguments
  • ConstructorParameters
  • Tuple
  • Array
  • ReadonlyArray
  • Tuple
  • Union
  • Intersection
  • Branded types
  • Mapped types
  • Conditional types
  • Indexed access types
  • Template literal types
  • Distributive conditional types
  • Narrowing
  • Widening
    *Substitution

在本文中,我们将介绍 TypeScript 工具类型的一些最常用的类型,并展示如何使用它们来创建新的类型。

Partial

Partial 类型可以将T中所有属性转换为可选属性。返回类型是 { [K in keyof T]?: T[K] }。

例如,我们可以使用 Partial 类型来创建一个可选的用户信息类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type OptionalUser = Partial<User>;

const user: OptionalUser = {
  name: 'John',
  age: 30,
};

Required

Required 类型与 Partial 类型正好相对应,它可以将T中所有属性转换为必填属性。返回类型是 { [K in keyof T]-: T[K] }。

例如,我们可以使用 Required 类型来创建一个必填的用户信息类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type RequiredUser = Required<User>;

const user: RequiredUser = {
  name: 'John',
  age: 30,
  email: 'john@example.com',
};

Readonly

Readonly 类型可以将T中所有属性转换为只读属性。返回类型是 { readonly [K in keyof T]: T[K] }。

例如,我们可以使用 Readonly 类型来创建一个只读的用户信息类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type ReadonlyUser = Readonly<User>;

const user: ReadonlyUser = {
  name: 'John',
  age: 30,
  email: 'john@example.com',
};

user.name = 'Bob'; // Error: Cannot assign to 'name' because it is read-only

Record

Record 类型可以创建一个新的类型,该类型具有指定键和值类型的属性。返回类型是 { [K in keyof T]: U }。

例如,我们可以使用 Record 类型来创建一个新的用户类型,该类型具有字符串键和数字值:

type User = Record<string, number>;

const user: User = {
  'John': 30,
  'Mary': 25,
  'Bob': 40,
};

Pick

Pick 类型可以从T中挑选出指定的属性,创建一个新的类型。返回类型是 { [K in keyof T]: T[K] }。

例如,我们可以使用 Pick 类型来从用户类型中挑选出姓名和年龄属性,创建一个新的类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type UserExcerpt = Pick<User, 'name' | 'age'>;

const user: UserExcerpt = {
  name: 'John',
  age: 30,
};

Omit

Omit 类型与 Pick 类型正好相对应,它可以从T中省略指定的属性,创建一个新的类型。返回类型是 { [K in keyof T]-: T[K] }。

例如,我们可以使用 Omit 类型从用户类型中省略电子邮件属性,创建一个新的类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type UserWithoutEmail = Omit<User, 'email'>;

const user: UserWithoutEmail = {
  name: 'John',
  age: 30,
};

Exclude

Exclude 类型可以从T中除去指定类型的属性,创建一个新的类型。返回类型是 { [K in keyof T]: T[K] extends U ? never : T[K] }。

例如,我们可以使用 Exclude 类型从用户类型中除去数字类型的属性,创建一个新的类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type UserWithoutNumbers = Exclude<User, number>;

const user: UserWithoutNumbers = {
  name: 'John',
  email: 'john@example.com',
};

NonNullable

NonNullable 类型可以从T中除去所有可选属性,创建一个新的类型。返回类型是 { [K in keyof T]-: NonNullable<T[K]> }。

例如,我们可以使用 NonNullable 类型从用户类型中除去所有可选属性,创建一个新的类型:

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

type NonNullableUser = NonNullable<User>;

const user: NonNullableUser = {
  name: 'John',
  age: 30,
  email: 'john@example.com',
};

Nullable

Nullable 类型与 NonNullable 类型正好相对应,它可以将T中所有属性转换为可选属性。返回类型是 { [K in keyof T]?: T[K] }。

例如,我们可以使用 Nullable 类型将用户类型中所有属性转换为可选属性,创建一个新的类型:

interface User {
  name: string;
  age: number;
  email: string;
}

type NullableUser = Nullable<User>;

const user: NullableUser = {
  name: 'John',
  email: 'john@example.com',
};

Parameters

Parameters 类型可以获取函数的参数类型。返回类型是 (...args: T) => R。

例如,我们可以使用 Parameters 类型获取函数的参数类型:

function add(a: number, b: number): number {
  return a + b;
}

type AddParameters = Parameters<typeof add>;

const params: AddParameters = [1, 2];

Arguments

Arguments 类型可以获取函数的参数值。返回类型是 T。

例如,我们可以使用 Arguments 类型获取函数的参数值:

function add(a: number, b: number): number {
  return a + b;
}

function callAdd(args: Arguments<typeof add>) {
  const result = add(...args);
  console.log(result);
}

callAdd([1, 2]); // 3

ConstructorParameters

ConstructorParameters 类型可以获取构造函数的参数类型。返回类型是 (...args: T) => void。

例如,我们可以使用 ConstructorParameters 类型获取构造函数的参数类型:

class User {
  constructor(public name: string, public age: number) {}
}

type UserConstructorParameters = ConstructorParameters<typeof User>;

const params: UserConstructorParameters = ['John', 30];

Tuple

Tuple 类型可以创建一个固定长度的数组类型。返回类型是 [T1, T2, ..., Tn]。

例如,我们可以使用 Tuple 类型创建一个固定长度的数组类型:

type Point = [number, number];

const point: Point = [1, 2];

Array

Array 类型可以创建一个数组类型。返回类型是 Array

例如,我们可以使用 Array 类型创建一个数组类型:

type Numbers = Array<number>;

const