Typescript与后端接口类型对接如何编写的更优雅?
问题是这样的,ant-design
的DatePicker
组件的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个回答
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);
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容