TypeScript Utility Types的源码实现

658 阅读2分钟

keyofin

  • keyof 可以用来取得一个对象接口的所有 key 值.
interface Foo {
  name: string;
  age: number
}
type T = keyof Foo // -> "name" | "age"
  • in 则可以遍历枚举类型, 例如
type Keys = "a" | "b"
type Obj =  {
  [p in Keys]: any
} // -> { a: any, b: any 
  • 联合类型(Union Types)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值。

注意:只能赋值指定的类型,如果赋值其它类型就会报错。

创建联合类型的语法格式如下:

Type1|Type2|Type3 

Record<Keys,Type>

构造一个对象类型,它的property是Keys,而property value 是Type。 这个实用类型工具可以用来把一个类型属性映射到另一个类型。

interface CatInfo {
  age: number;
  breed: string;
}

type CatName = "miffy" | "boris" | "mordred";

const cats: Record<CatName, CatInfo> = {
  miffy: { age: 10, breed: "Persian" },
  boris: { age: 5, breed: "Maine Coon" },
  mordred: { age: 16, breed: "British Shorthair" },
};

其源码实现为:

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

Partial<Type>

Partial得到所给类型的所有子集类型。即 将某个类型的所有属性变为可选(optional)。 其源码实现为:

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

Required<Type>

Required是Partial的反义词,即 将某个类型的所有属性都变成必选。实现原理如下:

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

Pick<Type, Keys>

从 T 中取出 一系列 K 的属性

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

Extract<Type, Union>

从Union Type中取出某个Type

type Extract<T, U> = T extends U ? T : never;

Exclude<Type, ExcludedUnion>

从Type中去掉ExcludedUnion的类型

type Exclude<T, U> = T extends U ? never : T;

Omit<Type, Keys>

去掉Type中的某些属性,是Pick的反义词。用之前的 PickExclude 进行组合, 实现忽略对象某些属性功能, 源码如下

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>

// 使用
type Foo = Omit<{name: string, age: number}, 'name'> // -> { age: number }

ReturnType<Type>

在阅读源码之前我们需要了解一下 infer 这个关键字, 在条件类型语句中, 我们可以用 infer 声明一个类型变量并且对它进行使用, 我们可以用它获取函数的返回类型, 源码如下

type ReturnType<T> = T extends (
  ...args: any[]
) => infer R
  ? R
  : any;

其实这里的 infer R 就是声明一个变量来承载传入函数签名的返回值类型, 简单说就是用它取到函数返回值的类型方便之后使用. 具体用法

function foo(x: number): Array<number> {
  return [x];
}
type fn = ReturnType<typeof foo>; // fn ===> number[]

Parameters<Type>

构造一个函数类型的参数对象的元组类型

例子

declare function f1(arg: { a: number; b: string }): void;

type T0 = Parameters<() => string>;
     
type T0 = []
type T1 = Parameters<(s: string) => void>;
     
type T1 = [s: string]
type T2 = Parameters<<T>(arg: T) => T>;
     
type T2 = [arg: unknown]
type T3 = Parameters<typeof f1>;
     
type T3 = [arg: {
    a: number;
    b: string;
}]

其源码实现为:

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

参考链接: