Typescript 一些高阶玩法

avatar
前端切图仔 @豌豆公主

typescript 自带了很多工具类型,通过看它的源码我们可以学习到 很多技巧 ,将它进行组合可以发挥无穷的潜力。以下是我总结的非常实用的技巧:

  1. 根据 model 的某些属性查询对象列表
type Student = { // 定义model
	id: number; // 主键
	name: string;
	age: number;
}

interface IQuery<T> {
  select(params: Partial<T>): T[];
}

class QueryStudent implements IQuery<Student> {
  select(params: Partial<Student>): Student[] {
    // @todo
  }
}

合理的使用 T(范型) 和 Partial 工具类型,可以帮助我们节约很多类型声明,Partial 将类型中的字段全变成可选类型,这样参数 params 的 key 就锁定在了 T 类型所拥有的 key

  1. 根据 model 更新数据

更新数据一般情况下是需要指定唯一id的,这个时候我们就需要用到类型推导了:

type PropsRequired<T, S extends keyof T> = {
  [k in S]-?: T[k]
}; // 这个地方也可以是 Required<Pick<T, S>>
type ModelUpdateParams<T, S extends keyof T> = Partial<Pick<T, Exclude<keyof T, S>>> & PropsRequired<T, S>; // 用自带的工具组合: Partical<Omit<T, S>> & Required<Pick<T, S>>;
class StudentModel {
	public update(params: ModelUpdateParams<Student, 'id'>) {
		// @todo 
	}
}

ModelUpdateParams 类型的推导在于将非必须的字段取出来变成 Paritial 然后 和 必须的字段进行联合, 这样update的参数就必须包含有指定的字段名id了。

  1. 类 valueOf 推导

在 typescript 文档中有看到 keyof 但是却没有 valueOf,其实有变通的方案:

type FunctionPropKeys<T> = {
  [k in keyof T]: T[k] extends Function ? k : never;
}[keyof T]; // 这个写法就类似于 valueOf 了,取出了是函数类型的key

type FunctionProps<T> = Pick<T, FunctionPropKeys<T>>; // 我们声明了一个提取函数属性的类型