概述
接口数据类型与表单提交数据类型,在大多数情况下,大部分属性的类型是相同的,但很少能做到完全统一。
我在之前的工作中经常为了方便,直接将接口数据类型复用为表单内数据类型,在遇到属性类型不一致的情况时会使用any
强制忽略类型错误。
后来经过自省与思考,这种工作模式会引起各种隐藏bug,一定有更好的工程解决方案。
我的答案就是:为表单提交数据单独定义类型!
类型解说
接口定义的请求体类型
请求数据类型
type RequestBody = {
name?: string
count?: number
groupIds?: number[]
startDate?: string // YYYY-MM-DD
}
表单提交数据类型定义
type FormValue = {
name?: string
count?: number
groupIds?: string
startDate?: Moment
}
有了该类型,我们可以方便的将该类型使用在表单实例上
const [form] = Form.useForm< FormValue >()
类型复用优化
如果表单的数据类型和接口提交的数据类型完全一致,当然可以共用一个,但现实世界这种情况几乎没有。
大多数情况是可以复用一些接口的属性到表单的数据类型中,例如上面的两个数据结构,其中 name、id 属性是相同的,则FormValue 可以优化为
type FormValue = Pick< RequestBody, 'name' | 'count' > {
groupIds?: string
startDate?: Moment
}
Form.Item 限定 name 优化
应用此时表单组件的name
约束就应为我们自定义的表单数据类型FormValue
,定义约束组件
const FormItem = Form.Item as React.FC<
Omit< FormItemProps, 'name' > & {
name: keyof FormValue
}
>
应用该约束组件
< FormItem label="名称" name="name" > ...
数据转换
在表单的onFinish
提交过程中,需要一个将FormValue(表单数据)转换为RequestBody(提交数据)的函数,类型定义如下:
const formValueToRquestBody = (values: FormValue): RequestBody => {
return {
name: values.name,
id: values.id,
groupIds: values.groupIds.split(',').map(n => Number(n)),
startDate: values.startDate?.format('YYYY-MM-DD'),
}
}
复杂表单类型
复杂表单有些表单数据并非一层的key => value
,而是多层树状或数组结构。
例如:提交数据结构
type FormValue = {
name: string
rule: {
min: number
max: number
}
}
表单中关于rule 的写法为:
< Form.Item name={['rule', 'min']}>
这种情况下,name
不再是简单的字符串,应该如何用类型约束?
如果可以我希望使用类型工具,兼容多层表单数据结构,但一直没成功。
我目前的方法是,为该表单层级安排一个专用类型,该方法会有些写的麻烦,但胜在能准确的定义好类型。
我在采用该方法校验表单name数据时发现了几个很难发现的拼写错误,提前制止了测试同学提bug过来。
例如为rule
属性定义单独的RuleFormItem
:
import type { FormItemProps } from 'antd'
const RuleFormItem = Form.Item as React.FC<
Omit< FormItemProps, 'name'> & {
name: ['rule', keyof FormValue['rule']]
}
>
调用时
< RuleFormItem label="min" name={['rule', 'min']}> ...
此时数组中的 rule 与 min 都能收到类型的保护。
泛型抽象
export type TypedFormItem< T > = React.FC<
Omit< FormItemProps, 'name' > & {
name: T
}
>
应用泛型
const RuleFormItem = Form.Item as TypedFormItem< keyof FormValue >
恭喜,现在你的表单已经被类型完整的保护了。
作者:京东零售 王凡
来源:京东有开发者社区 转载请注明来源
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容