如何在RHF结合Zod的superrefine/refine时修改默认错误信息?
解决Zod自定义错误提示与路径指定问题
一、替换默认的"Expected object, received array"错误提示
你遇到的默认错误提示是因为Zod优先执行类型校验:你的templateCode初始值是数组,但schema定义为object,触发了invalid_type类型错误。要替换这个提示,有两种实用方式:
方式1:直接给object类型添加自定义错误信息
修改templateCode的object schema,通过invalid_type_error参数覆盖默认提示:
const templateDefaultsSchema = z.array( z.union([ z.object({ templateCode: z .object({ tenantName: z.string(), tenantId: z.number(), }) .passthrough({ invalid_type_error: "An option has to be selected" // 替换默认类型错误提示 }) .superRefine((val, ctx) => { // 这里写实际校验逻辑,比如判断是否选中有效选项 if (!val.tenantId) { // 示例:若tenantId不存在则报错 ctx.addIssue({ code: z.ZodIssueCode.custom, message: "请选择有效的模板选项", }); } }), // ...其他字段 }), // ...其他union类型 ]) );
方式2:兼容初始数组类型,再通过refine校验选中状态
如果需要保留初始数组的兼容,可以调整schema允许数组类型,再通过refine验证最终是否选中对象:
const templateCodeSchema = z.union([ z.array(z.any()), // 允许初始数组类型 z.object({ tenantName: z.string(), tenantId: z.number(), }).passthrough() ]).refine((val) => { // 校验逻辑:最终必须是选中的对象,而非数组 return typeof val === 'object' && !Array.isArray(val) && val.tenantId; }, { message: "An option has to be selected" }); const templateDefaultsSchema = z.array( z.union([ z.object({ templateCode: templateCodeSchema, // ...其他字段 }), // ...其他union类型 ]) );
二、superRefine/refine中的路径指定问题
在templateCode字段的superRefine里,不需要指定完整路径(比如["templateDefaults", 0, "templateCode"]),只需要写相对当前字段的路径["templateCode"]即可:
.superRefine((val, ctx) => { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "自定义提示", path: ["templateCode"] // 仅需相对当前字段的路径 }); })
Zod会自动结合上层schema的路径(数组索引、父字段名),最终React Hook Form会自动映射到完整的templateDefaults[0].templateCode路径,确保错误信息正确绑定到对应的表单控件上。
内容的提问来源于stack exchange,提问作者Shiladitya Thakur
相关产品推荐
相关产品推荐

