Typescript与后端接口类型对接如何编写的更优雅?

作者站长头像
站长
· 阅读数 6

问题是这样的,ant-designDatePicker组件的value属性一般会被要求接收一个moment对象,

ant-design 是一个前端框架, moment是一个前端处理日期的库

不过接口返回的往往是一个Date类型的字符串所以我需要把数据moment化

const result = await fetchData() // 接口返回数据
result.date = moment(result.date) // moment化
setFetchResult(result)

为了能在前端中也得到moment化后的代码提示

// 接口返回定义的数据结构
interface IFetchData {
  ...
  date: Date
  ...
}
// 前端
interface IFontEndResult extends IFetchDate {
    fontEndDate: Moment.moment
}

我就需要用继承的方式,然后date改名成fontEndDate(因为用的是继承所以要改名

这样子引用时没问题了,在使用过程中可以得到所有moment库中函数的提示

但是在调用接口(比如上传)的时候就需要转换一次上传的参数

// 上传的函数的类型定义
function submit (param:IFetchData) => Promise<response>
// 实际使用
const value = getFormValue()
const param = { ...value, ...{ date: value.fontEndDate.format()}} // 多出来的步骤
submit(param)

这样比较麻烦,有没有更优雅的方式去编写最前面的IFontEndResult接口呢?

有一些特殊要求:

  • moment化步骤不能放在JSX中执行
  • 不能修改原始接口的interface
  • 尽量不要用断言
回复
1个回答
avatar
test
2024-07-10

更改 Typescript 类型方案:

import moment from "moment";

// 接口返回定义的数据结构
interface IFetchData {
  // ...
  date: Date
  // ...
}

// 前端
interface IFontEndResult extends Omit<IFetchData, "date"> {
  date: moment.Moment
}

// 或者
type IFontEndResult = Omit<IFetchData, "date"> & {
  date: moment.Moment
}

以下为原答案:

写两个函数用于 API <--> From Values 间双向转换。这种模式不仅仅可以解决这个字段,有其他地方不适配也可以解决。


/** 接口返回转 FormValues */
export const responseToFormValues = (resp: IFetchData): IFormValues => { /** moment 化等... */ }

/** FormValues 转接口参数 */
export const formValuesToRequestBody = (values: IFormValues): IFetchData => { /** 转 date 等... */ }

//=== 使用 ===

// 初始化
const result = await fetchData(); // 接口返回数据
const formValues = responseToFormValues(result); // moment化
setFetchResult(formValues);

// 提交
const values = getFormValue();
const param = formValuesToRequestBody(value);
submit(param);
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容