TypeScript要想玩的6,实用工具类型必须知(三)

68 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

很多初学者在学习TypeScirpt这门语言都非常的吃了,学习了基本的接口、泛型、联合类型、元组等等一系列关于TypeScript知识。

但是在实际开发中去定义类型又非常不熟练,并且又有一种约束的感觉。总的来说对开发体验感极差从而导致对TypeScript这一门语言产生厌恶或者恐惧,从而 any 一把梭。

实际上,学习TypeScript并非一件容易的事,它是一个类型世界。我自己在初学TypeScirpt时也是产生这种恐惧的感觉,并没有给我的开发带来便利的感觉。到后面用多了才明白它的好。

TypeScript 工具类型

接下来主要是介绍一下 TypeScript 提供给我们的一些工具类型。

在文章中TypeScript要想玩的6,实用工具类型必须知(一)TypeScript要想玩的6,实用工具类型必须知(三)已经介绍过了十种实用工具类型,接下来就继续介绍最后的一些工具类型。

实现源码:

type CustomOmitType<T, K extends keyof T> = {
  [P in keyof T as P extends K ? never : P]: T[P];
};

ConstructorParameters<Type>

ConstructorParameters<Type> 获取类构造函数的参数的类型

先看看研究如何去对类的静态、动态部分进行类型约束

参考一下官方文档的讲解 官方文档

// 对类的静态部分 构造函数、静态变量、静态方法等进行约束
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
  currentTime: Date;
}

// 对类想实例部分进行约束
interface ClockInterface {
  tick(): void;
}

// 实现类接口对类的静态部分、实例部分约束写法:
const Clock: ClockConstructor = class Clock implements ClockInterface {
  constructor(h: number, m: number) {}
  static currentTime: Date = new Date();
  tick() {
    console.log("beep beep");
  }
};

let clock = new Clock(12, 17);
// TS自带全局接口
// interface ErrorConstructor {
//   new(message?: string): Error;
//   (message?: string): Error;
//   readonly prototype: Error;
// }
type TestConstructorParametersType = ConstructorParameters<ErrorConstructor>;

// 转换为如下类型
type TestConstructorParametersType = [message?: string | undefined]

实现源码:

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

ReturnType<Type>

ReturnType<Type> 构造一个返回函数类型T的返回值的类型

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

type TestReturnType = ReturnType<typeof f1>;

// 转换为如下类型
type TestReturnType = {
    a: number;
    b: string;
}

实现源码:

type CustomReturnType<T extends () => any> = T extends () => infer X
  ? X
  : never;

InstanceType<Type>

InstanceType<Type> 返回 Type类 的实例部分的类型

// 对类的静态部分 构造函数、静态变量、静态方法等进行约束
interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
  currentTime: Date;
}

// 对类想实例部分进行约束
interface ClockInterface {
  tick(): void;
}

// 实现类接口对类的静态部分、实例部分约束写法:
const Clock: ClockConstructor = class Clock implements ClockInterface {
  constructor(h: number, m: number) {}
  static currentTime: Date = new Date();
  tick() {
    console.log("beep beep");
  }
};

type TestCustomInstanceType = InstanceType<typeof Clock>;

// 转换为如下类型
type TestCustomInstanceType = ClockInterface

实现源码:

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

ThisParameterType<Type>

ThisParameterType<Type> 返回函数Type中参数名为 this的类型,如果没有则返回unknown

function toHex(this: number) {
  return this.toString(16);
}

type TestThisParameterType = ThisParameterType<typeof toHex>;

// 转换为如下类型
type TestThisParameterType = number

实现源码:

type CustomThisParameterType<T extends (this: any, ...args: any) => any> =
  T extends (this: infer X, ...args: any) => any ? X : unknown;

OmitThisParameter<Type>

OmitThisParameter<Type> 将函数Type中函数名为 this的类型移除,返回一个新的函数类型

function toHex(this: number) {
  return this.toString(16);
}

type TestOmitThisParameter = OmitThisParameter<typeof toHex>;

// 转换为如下类型
type TestOmitThisParameter = () => string

实现源码:

type CustomOmitThisParameter<T extends (this: any, ...args: any) => any> =
  T extends (this: any, ...args: infer A) => infer X
    ? (...args: A) => X
    : never;

ThisType<Type>

ThisType<Type> 构造一个对象中的所有函数的this指向类型,它只能在对象内的类型声明时使用

查看官方源码可以看到它的实现方式:interface ThisType<T> { } 其实我也还不理解它的具体使用场景

type Point = {
  x: number;
  y: number;
  moveBy: (dx: number, dy: number) => void;
} & ThisType<{ message: string }>;

let p: Point = {
  x: 10,
  y: 20,
  moveBy(dx, dy) {
    this; // {message:string}
  },
};

四个内置字符串工具类型

  • Uppercase<StringType> 将字符串字母全部大写
  • Lowercase<StringType> 将字符串字母全部小写
  • Capitalize<StringType> 将字符串首字母都大写
  • Uncapitalize<StringType> 将字符串首字母都小写

总结

TypeScript的实用工具类型到这里就全部介绍完成。其中有一些工具类型在平时开发当中使用的频率还是蛮高的。所以还是需要不断积累学习在开发中使用这些工具类型。

另外在GitHub有一个开源项目是关于TS类型体操 的,在那里可以提高我们的TS类型声明。