如何使用Yup Schema校验固定长度元组数组与联合类型对象?
基于Yup实现指定TS接口的完整校验
固定长度字符串元组(对应tuple字段)
- 针对固定长度、元素有序的元组场景,优先使用Yup原生
tuple校验器,不要用动态长度的yup.array()做基础实现 - 元组校验器需要按位置声明每个位置的元素规则,匹配“两个位置都必须是字符串”的要求时,依次传入两个字符串校验规则即可
yup.tuple()会原生校验数组长度,传入数组长度不等于声明的元素数量、缺元素、多元素都会直接触发校验错误- 原生实现代码:
// 严格匹配长度为2的字符串元组 const tupleSchema = yup.tuple([ yup.string().required(), yup.string().required() ]) - 若使用的是不支持tuple方法的旧版Yup,可使用数组校验加自定义测试的兜底实现:
const tupleSchema = yup.array() .of(yup.string().required()) .test('tuple-length', '元组必须严格包含2个字符串元素', val => val?.length === 2)
可替代联合结构对象(对应alt字段)
- 针对无公共判别字段的二选一对象结构,使用Yup原生
union校验器,传入两个候选结构的schema即可 - 每个候选对象schema必须开启
strict: true严格模式,否则Yup会默认忽略传入对象的多余字段,导致校验规则比TS接口定义更宽松 - 原生实现代码:
// 候选结构1:仅包含必填foo字符串字段 const fooStruct = yup.object({ foo: yup.string().required() }).strict() // 候选结构2:仅包含必填bar字符串字段 const barStruct = yup.object({ bar: yup.string().required() }).strict() const altSchema = yup.union([fooStruct, barStruct]) - 若使用的是不支持union方法的旧版Yup,可使用混合类型校验加自定义测试的兜底实现:
const altSchema = yup.mixed().test( 'alt-structure-match', '结构必须是仅含foo字符串、或仅含bar字符串的对象', value => fooStruct.isValidSync(value) || barStruct.isValidSync(value) )
整合为完整接口校验Schema
将两个字段的校验规则合并到总对象schema中,即可完全匹配Example接口的结构要求:
const exampleSchema = yup.object({ // 严格校验2元素字符串元组 tuple: yup.tuple([ yup.string().required(), yup.string().required() ]).required(), // 严格校验二选一联合结构 alt: yup.union([ yup.object({foo: yup.string().required()}).strict(), yup.object({bar: yup.string().required()}).strict() ]).required() })
关键注意事项
- 所有自定义对象校验必须显式开启严格模式,避免多余字段绕过校验
- 元组校验如果不使用原生tuple方法,一定要单独添加长度判断规则,否则传入3个及以上字符串元素的数组会被错误放行
- 若两个候选联合结构后续新增公共可判别字段,建议切换为
discriminatedUnion实现,可提升校验性能、优化报错提示的精准度
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

