Typescript 工具类型集合

343 阅读5分钟

理解不太深,如果有不对的地方,欢迎指出,一起学习

ts-type-challenges 这里是 TS 体操类型挑战的题解,目前还没有做完

操作符

typeof:获取变量的声明或者类型

const v1 = 1234
const v2 = 'string'
const v3 = {
  p: 123
}
const v4 = [1, 2, 3, 4]

type t1 = typeof v1 // type t1 = 1234
type t2 = typeof v2 // type t2 = "string"
type t3 = typeof v3
// type t3 = {
//     p: number;
// }
type t4 = typeof v4 // type t4 = number[]

keyof:获取某种类型的所有 key 值,并返回联合类型

const v = {
  p: 123,
  p1: 'string'
}

type t = keyof typeof v   // type t = "p" | "p1"

extends:泛型约束。还可以理解为遍历操作等

type v = 123 | 'string' | 456
type p = v extends number | string ? true : false // type p = true

// v extends number | string
// 可以理解为
// 123 extends number | string
// 'string' extends number | string

as:断言。目前主要用于属性 key 值的逻辑处理

// type-challenges - 8
// 实现一个通用 MyReadonly2<T, K>,它带有两种类型的参数 T 和 K。
// K 指定应设置为 Readonly 的 T 的属性集。如果未提供 K,则应使所有属性都变为只读,就像普通的 Readonly<T> 一样

type MyReadonly2<T, K extends keyof T = keyof T> =
  {
    readonly [P in keyof T]: T[P]
  } & {
    // 这里理解为:如果 P 在 K 的约束类型内则返回 never,否则返回 P。
    // 返回 never 则表示在当前类型内剔除 P
    [P in keyof T as P extends K ? never : P]: T[P]
  }

in:用来遍历枚举类型

infer:声明一个类型变量

type f = (...args: any) => string

type Parameter<T extends (...args: any) => any> = 
  // 这里的 infer R 表示在当前环境中声明一个类型变量 R,用于后续逻辑的操作
  T extends (...args: any) => infer R ? R : never

type r = Parameter<f> // type r = string

内置类型工具

在 ts 的开发中,如果熟悉内置的已有的工具类型,还是能极大的提升开发效率,也使类型更加规范。

Awaited

说明:递归地解开 awaited 类型。如果 then 不可调用则返回 never。模拟 await 的行为。

type Awaited<T> =
    T extends null | undefined ? T :
        T extends object & { then(onfulfilled: infer F): any }
            ? F extends ((value: infer V, ...args: any) => any) 
                ? Awaited<V> 
                : never 
            : T;

示例:

type promise = Promise<Promise<number>>
type P1 = Awaited<promise>
// p1 === number

Partial

说明:使类型 T 中的所有属性都变为可选的。

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

示例:

type t1 = {
  num: number
  age: number
  name: string
}
type t2 = Partial<t1>

// type t2 = {
//     num?: number | undefined
//     age?: number | undefined
//     name?: string | undefined
// }

Required

说明:使 T 中的所有属性都是必需的。

这里 - 的意思可以理解为取反, -? 是必填, -readonly 是可写

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

示例:

type t1 = {
  num?: number
  age?: number
  name: string
}
type t2 = Required<t1>

// type t2 = {
//     num: number
//     age: number
//     name: string
// }

Readonly

说明:使 T 中的所有属性为只读

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

示例:

type t1 = {
  num?: number
  age?: number
  name: string
}
type t2 = Readonly<t1>

// type t2 = {
//   readonly num?: number | undefined;
//   readonly age?: number | undefined;
//   readonly name: string;
// }

Pick

说明:从 T 中,把集合 K 中的属性重新组装成一个新的类型。

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

示例:

type t1 = {
  num?: number
  age?: number
  name: string
}
type t2 = 'num' | 'name'
type t3 = Pick<t1, t2>

// type t3 = {
//   num?: number | undefined;
//   name: string;
// }

Record

说明:构造一个具有类型 T 的属性集 K 的类型。

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

示例:

type t1 = 'num' | 'age' | 'name'
type t2 = Record<t1, number>

// type t2 = {
//   num: number;
//   age: number;
//   name: number;
// }

Exclude

说明:从 T 中排除集合 U 的类型并返回一个新的类型集合。

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

示例:

type t1 = 'num' | 'age' | 'name'
type t2 = Exclude<t1, 'num'>

// type t2 = "age" | "name"

Extract

说明:从 T 中提取那些可分配给 U 的类型。与 Exclude 相反。

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

示例:

type t1 = 'num' | 'age' | 'name'
type t2 = Extract<t1, 'num'>

// type t2 = "num"

Omit

说明:构造一个除类型 K 中的属性外具有 T 属性的类型。

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

示例:

type t1 = {
  num?: number
  age?: number
  name: string
}
type t2 = Omit<t1, 'num'>

// type t2 = {
//   age?: number | undefined;
//   name: string;
// }

NonNullable

说明:从 T 中排除 nullundefined

type NonNullable<T> = T extends null | undefined ? never : T;

示例:

type t1 = 'num' | 'age' | 'name' | null | undefined
type t2 = NonNullable<t1>

// type t2 = "num" | "age" | "name"

Parameters

说明:获取函数类型的参数。

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

示例:

type t1 = (value: number, name: string) => void
type t2 = Parameters<t1>

// type t2 = [value: number, name: string]

ConstructorParameters

说明:获取构造函数类型的参数。

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

示例:

type t1 = new (v: string) => void
type t2 = ConstructorParameters<t1>

// type t2 = [v: string]

ReturnType

说明:获取函数类型的返回类型。

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

示例:

type t1 = (value: number, name: string) => string
type t2 = ReturnType<t1>

// type t2 = string

InstanceType

说明:获取构造函数类型的返回类型。

type InstanceType<T extends abstract new (...args: any) => any> = 
    T extends abstract new (...args: any) => infer R ? R : any;

示例:

type t1 = new (v: string) => string
type t2 = InstanceType<t1>

// type t2 = string

Uppercase

说明:将字符串转为为大写。intrinsic 表示为可能目前的 ts 语法不好直接实现,直接用 intrinsic 标识为内置实现。

type Uppercase<S extends string> = intrinsic;

示例:

type t1 = 'value'
type t2 = Uppercase<t1>

// type t2 = "VALUE"

Lowercase

说明:将字符串转为为小写。intrinsic 表示为可能目前的 ts 语法不好直接实现,直接用 intrinsic 标识为内置实现。

type Lowercase<S extends string> = intrinsic;

示例:

type t1 = 'VALUE'
type t2 = Lowercase<t1>

// type t2 = "value"

Capitalize

说明:将字符串字面值类型的第一个字符转换为大写。intrinsic 表示为可能目前的 ts 语法不好直接实现,直接用 intrinsic 标识为内置实现。

type Capitalize<S extends string> = intrinsic;

示例:

type t1 = 'value'
type t2 = Capitalize<t1>

// type t2 = "Value"

Uncapitalize

说明:将字符串字面量类型的第一个字符转换为小写。intrinsic 表示为可能目前的 ts 语法不好直接实现,直接用 intrinsic 标识为内置实现。

type Uncapitalize<S extends string> = intrinsic;

示例:

type t1 = 'VALUE'
type t2 = Uncapitalize<t1>

// type t2 = "vALUE"

自定义工具类型

Merge

说明:将两个类型合并成一个类型,第二个类型的键会覆盖第一个类型的键。

type Merge<F, S> = {
  [K in (keyof F | keyof S)]: 
      K extends keyof S ? S[K] : K extends keyof F ? F[K] : never
}

示例:

type t1 = {
  age?: number
  name: string
}
type t2 = {
  num?: number
  age?: string
}
type t3 = Merge<t1, t2>

// type t3 = {
//   age: string | undefined;
//   name: string;
//   num: number | undefined;
// }

后续慢慢收集其它有用的工具类型...