业务同学觉得TypeScript难/麻烦的一些事儿02

257 阅读3分钟

背景

在上一篇文章中,我们提到了组件参数和函数参数的关联关系。今天来看看另外一个TS类型问题,在编写TS类型时,我们会碰到一些固定格式的数据类型,比较典型的就是分页数据。来看个现状:

image-20241106111153416.png

我在一个比较新的项目中搜分页入参类型,发现同样的类型,重复定义了4遍。然后想再看看出参的类型是怎么定义的,发现,居然一个都没有。好好好,都搁这偷懒是吧,看返回类型复杂,直接不写了┓( ´∀` )┏

且看我出手整治一下这些“妖魔鬼怪”

自定义工具类型

分页入参

很简单,直接在全局的typings.d.ts声明类型

// typings.d.ts
declare type TRequestPage = {
  pageIndex: number;
  pageRows: number;
};

但这样有个问题,有筛选条件的话还需要人工拼接,这就不是一个好用的工具类型了

// typings.d.ts
declare type TRequestPage<T = {}> = Partial<T> & {
  pageIndex: number;
  pageRows: number;
};

定义了一个泛型接收筛选参数,跟分页参数做可选并集。但有部分场景,筛选参数是必传时,这个工具就用不了了,需要再优化一下

// typings.d.ts
declare type TRequestPage<T = {}, K extends keyof T = never> = {
  [O in Exclude<keyof T, K>]?: T[O];
} & {
  [P in K]: T[P];
} & {
  pageIndex: number;
  pageRows: number;
};

以上代码做了几个事情:

  1. 接收了泛型K,类似与Pick的剩余参数,并设置了默认值never,以适应筛选字段为非必传的场景
  2. 对泛型K的参数定义为必传,对T类型下除K泛型之外的参数定义为可选(因为我们业务场景中必传字段相对较少,所以优先默认全部转为可选,再显式传入必传字段,这也是在做工具方法时需要考虑的问题,可选与必传,什么样的场景居多,我们应该开什么样的口子给调用方)
  3. 使用了两个&符号将可选、必传、默认参数组合在一起,这是type类型限制的,不然类型推导不出来实际所需参数

当然还有一些边界情况我们没有处理:如何限制泛型T传入pageIndex等默认参数且改变了类型,这边就不深入探讨了

再来看看如何使用:

// xxx/types.ts
export type TTrainingOrgForm = {
  orgName: string;
  orgTypeId: string;
  validDay: number;
  parentId: number;
}
export type TTrainingOrgListReq = TRequestPage
// or
export type TTrainingOrgListReq = TRequestPage<TTrainingOrgForm>
// or
export type TTrainingOrgListReq = TRequestPage<TTrainingOrgForm,'orgName'>

:因为我们是在全局类型中使用declare做了类型声明,所以在使用时就无需再引入TRequestPage类型了

分页出参

出参相对来说就比较简单了,因为返回的数据较多且复杂,是否可选的定义则交由使用方定义,工具类型只做标准结构的定义。

// typings.d.ts
declare type TResponsePage<T> = {
  list: T[];
  total: number;
  pageNum: number;
  pageSize: number;
  size: number;
  startRow: number;
  endRow: number;
  pages: number;
};

使用:

// xxx/types.ts
export type TTrainingOrgList = {
  contactName: string;
  contactTel: string;
  createTime?: string;
  createUser?: string;
  orgId: number;
  orgName: string;
  // ....
}
export type TOrgEmployeeListReq = TResponsePage<TTrainingOrgList>

总结

同样的类型写了四遍,而且这么基础的类型也没有提取出来,哪怕封装的没有那么好,要迈出第一步。

现在写了这两个工具类型,但如果不在CR会上同步、检查,就等于白写,沟通很重要!!!

降低开发使用成本,提高技术探索意识