Ts常用的内置工具类型与实现(持续更新中...)

418 阅读3分钟

TS中有许多常用的工具类型映射类型,可以避免重复的类型定义。

在本文中,我们将ts的工具类型分为三类,分别是

  1. 对联合类型进行操作的(Exclude、Extract、NonNullable...)
  2. 对对象类型进行操作的(Partial、Pick、Omit...)
  3. 对函数类型进行操作的(ReturnType、Paramter...)

联合类型

1. Exclude<P,K>

Exclude接收两个范型P K,其中P是一个联合类型,K是P中的一个子类型,这个工具类型主要就是将P中的联合类型K给移除掉。

type TP = "foo" | "bar";
type TK = "bar";
type test = Exclude<TP, TK>; // "foo"

那我们如何实现一个自己的exclude呢,其实不难发现,exclude就是将P中的K给全部移除了,要实现这个,就需要我们用到ts中类型的分布式了。

type TP = "foo" | "bar";
type TK = "bar";

type MyExclude<P, K> = P extends K ? never : P;
type test = MyExclude<TP, TK>; // "foo"

其中把P分配给类型K进行比较,如果P是K的子类型,则返回never,如果不是则返回P 很容易发现,K是不受P约束的,就意味着TK中的字段不是TP的子类型也不会报错。 对此我们可以进一步对K进行约束。

type TP = "foo" | "bar";
type TK = "bar" | "oo";

type MyExclude<P, K extends P> = P extends K ? never : P;
type test = MyExclude<TP, TK>; //类型“TK”不满足约束“TP”,不能将类型“"oo"”分配给类型“TP”。

2. Exteact<P,K>

Extract接收两个范型P K,其中P是一个联合类型,K是P中的一个子类型,这个工具类型主要就是将P中的符合类型K的给提取出来。

type Person = {
  name: string;
  age: number;
  gender: 'male' | 'female';
};
type test = Extract<keyof Person, "name">; // 'name'

Extract主要就是将联合类型中指定的key给提取出来。所以我们可以很轻松实现。

type Person = {
  name: string; // 将类型改为string
  age: number;
  gender: 'male' | 'female';
};
type MyExtract<P,K> = P extends K ? P : never
type test = MyExtract<keyof Person, "name">; // "name"

同理我们也可使用范型约束K的入参

type Person = {
  name: string; // 将类型改为string
  age: number;
  gender: 'male' | 'female';
};
type MyExtract<P,K extends P> = P extends K ? P : never
type StringProps = MyExtract<keyof Person, "foo">; // Type '"foo"' does not satisfy the constraint 'keyof Person

3. NonNullable<T>

NonNullable 作用是从类型 T 中去除 null 和 undefined 类型,返回一个新的类型,即 T 类型中所有非 null 和 undefined 的类型。

type NullableString = string | null | undefined;
type NonNullableString = NonNullable<NullableString>; // string

那我们要实现一个NonNullable也非常简单了,同样也是用到了分布式,将undefined 以及null 从T中剔除掉即可。

type NullableString = string | null | undefined;
type MyNullableString<T> = T extends null|undefined ? never : T
type NonNullableString = MyNullableString<NullableString>; // string

对象类型

1.Partial<T>

它的作用是将类型 T 中所有属性变为可选属性,即将每个属性的类型从 T[K] 变为 T[K] | undefined

interface Person {
  name: string;
  age: number;
  gender: 'male' | 'female';
}

type PartialPerson = Partial<Person>;
// 等价于
// type PartialPerson = {
//   name?: string | undefined;
//   age?: number | undefined;
//   gender?: "male" | "female" | undefined;
// }

实现一个自己的Partial,只需遍历对象中的每一个字段,并将它改为可选就行了。

type MyPartial<T> = {
  [K in keyof T]?: T[K];
};

2.Pick<T,K>

它的作用是从类型 T 中选择指定的属性 K,返回一个新的类型,即只包含 T 类型中指定属性的子类型。

interface Person {
  name: string;
  age: number;
  gender: 'male' | 'female';
}

type PersonNameAndAge = Pick<Person, 'name' | 'age'>;
// 等价于
// type PersonNameAndAge = {
//   name: string;
//   age: number;
// }

实现自己的一个Pick,只需要遍历K中每一个元素并且从T中取出该元素对应的类型返回就行了,如果是则返回该元素,不是则返回never就行了。

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

3.Omit<T,K>

....