返回

Typescript 之类型工具:实用又万能!

前端

前言

Typescript 中默认内置了很多工具泛型,通过使用这些工具,可以使得我们定义类型更加灵活,高效。本文将会介绍常用泛型工具的使用技巧,以及对其实现原理进行相应的解析。

Partial

介绍

Partial<T> 用于将类型 T 中所有的属性都变为可选的。当我们不想让类型 T 中的所有属性都为必填时,可以使用 Partial 来放松对这些属性的要求。

使用示例

interface Person {
  name: string;
  age: number;
  gender: string;
}

// 定义一个可部分修改的 Person 类型
type PartialPerson = Partial<Person>;

// 使用 PartialPerson 类型来定义一个对象
const person: PartialPerson = {
  name: 'John',
  // age 和 gender 属性可以不指定
};

实现原理

Partial<T> 的实现原理是使用一个联合类型。对于类型 T 中的每个属性 key,Partial<T> 会创建一个新的键值对 [key: T[key]],其中 T[key] 是类型 T 中属性 key 的类型。然后,Partial<T> 将这些新的键值对与 T 中的原有属性一起组合成一个新的联合类型。

type Partial<T> = {
  [key in keyof T]?: T[key];
};

Required

介绍

Required<T> 用于将类型 T 中所有的属性都变为必填的。当我们想让类型 T 中的所有属性都为必填时,可以使用 Required 来强制要求这些属性必须要有值。

使用示例

interface Person {
  name?: string;
  age?: number;
  gender?: string;
}

// 定义一个必填的 Person 类型
type RequiredPerson = Required<Person>;

// 使用 RequiredPerson 类型来定义一个对象
const person: RequiredPerson = {
  name: 'John',
  age: 30,
  gender: 'male',
};

实现原理

Required<T> 的实现原理是使用一个交叉类型。对于类型 T 中的每个属性 key,Required<T> 会创建一个新的键值对 [key: T[key]],其中 T[key] 是类型 T 中属性 key 的类型。然后,Required<T> 将这些新的键值对与 T 中的原有属性一起组合成一个新的交叉类型。

type Required<T> = {
  [key in keyof T]-?: T[key];
};

Readonly

介绍

Readonly<T> 用于将类型 T 中所有的属性都变为只读的。当我们不想让类型 T 中的任何属性可以被修改时,可以使用 Readonly 来保护这些属性。

使用示例

interface Person {
  name: string;
  age: number;
  gender: string;
}

// 定义一个只读的 Person 类型
type ReadonlyPerson = Readonly<Person>;

// 使用 ReadonlyPerson 类型来定义一个对象
const person: ReadonlyPerson = {
  name: 'John',
  age: 30,
  gender: 'male',
};

// 尝试修改 person 对象的属性会报错
person.name = 'Jane'; // error: Cannot assign to 'name' because it is a read-only property.

实现原理

Readonly<T> 的实现原理是使用一个联合类型。对于类型 T 中的每个属性 key,Readonly<T> 会创建一个新的键值对 [key: readonly T[key]],其中 T[key] 是类型 T 中属性 key 的类型。然后,Readonly<T> 将这些新的键值对与 T 中的原有属性一起组合成一个新的联合类型。

type Readonly<T> = {
  readonly [key in keyof T]: T[key];
};

Pick

介绍

Pick<T, K> 用于从类型 T 中挑选出指定的属性 K,并组成一个新的类型。当我们只想使用类型 T 中的某些属性时,可以使用 Pick 来提取这些属性。

使用示例

interface Person {
  name: string;
  age: number;
  gender: string;
  address: string;
}

// 从 Person 类型中挑选出 name 和 age 属性
type NameAndAge = Pick<Person, 'name' | 'age'>;

// 使用 NameAndAge 类型来定义一个对象
const person: NameAndAge = {
  name: 'John',
  age: 30,
};

实现原理

Pick<T, K> 的实现原理是使用一个交叉类型。对于类型 T 中的每个属性 key,如果 key 存在于 K 中,则 Pick<T, K> 会创建一个新的键值对 [key: T[key]],其中 T[key] 是类型 T 中属性 key 的类型。然后,Pick<T, K> 将这些新的键值对与 T 中的原有属性一起组合成一个新的交叉类型。

type Pick<T, K extends keyof T> = {
  [key in K]: T[key];
};

Omit

介绍

Omit<T, K> 用于从类型 T 中排除指定的属性 K,并组成一个新的类型。当我们不想使用类型 T 中的某些属性时,可以使用 Omit 来去除这些属性。

使用示例

interface Person {
  name: string;
  age: number;
  gender: string;
  address: string;
}

// 从 Person 类型中排除 address 属性
type PersonWithoutAddress = Omit<Person, 'address'>;

// 使用 PersonWithoutAddress 类型来定义一个对象
const person: PersonWithoutAddress = {
  name: 'John',
  age: 30,
  gender: 'male',
};

实现原理

Omit<T, K> 的实现原理是使用一个交叉类型。对于类型 T 中的每个属性 key,如果 key 不存在于 K 中,则 Omit<T, K> 会创建一个新的键值对 [key: T[key]],其中 T[key] 是类型 T 中属性 key 的类型。然后,Omit<T, K> 将这些新的键值对与 T 中的原有属性一起组合成一个新的交叉类型。

type Omit<T, K extends keyof T> = {
  [key in Exclude<keyof T, K>]: T[key];
};

Conclusion

以上便是 Typescript 中常用工具类型的一些介绍和使用示例,希望对您有所帮助。这些工具类型可以帮助我们定义更加灵活和高效的类型,从而使我们的代码更加健壮和易于维护。