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

问题是这样的,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.9k
2 个回答

更改 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);

把DatePicker这个组件再封装一下啊,让它接受Date类型,内部转成moment啊

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏