如何在Zod Error Map中实现自定义必填项错误提示?
自定义Zod必填项错误提示方案
问题描述
想要实现Zod错误映射的自定义消息,但不清楚如何在错误映射中统一设置必填项提示(required_message),因为ZodIssueCode枚举里找不到对应的代码,此前只能在每个schema字段中手动设置。
当前错误映射代码:
const customErrorMap: z.ZodErrorMap = (issue, ctx) => { switch (issue.code) { case z.ZodIssueCode.invalid_type: if (issue.expected === "string") { return { message: 'invalid_string' }; } else if (issue.expected === "number") { return { message: 'invalid_number' }; } else { return { message: 'invalid_type' }; } case z.ZodIssueCode.custom: return { message: issue.message || 'custom_error' }; case z.ZodIssueCode.invalid_union: return { message: 'invalid_union' }; case z.ZodIssueCode.invalid_enum_value: return { message: 'invalid_enum_value' }; case z.ZodIssueCode.unrecognized_keys: return { message: 'unrecognized_keys' }; case z.ZodIssueCode.invalid_arguments: return { message: 'invalid_arguments' }; case z.ZodIssueCode.invalid_return_type: return { message: 'invalid_return_type' }; case z.ZodIssueCode.invalid_date: return { message: 'invalid_date' }; case z.ZodIssueCode.invalid_string: return { message: 'invalid_string' }; case z.ZodIssueCode.too_small: return { message: 'too_small' }; case z.ZodIssueCode.too_big: return { message: 'too_big' }; case z.ZodIssueCode.invalid_intersection_types: return { message: 'invalid_intersection_types' }; case z.ZodIssueCode.not_multiple_of: return { message: 'not_multiple_of' }; case z.ZodIssueCode.not_finite: return { message: 'not_finite' }; default: return { message: ctx.defaultError }; } }
ZodIssueCode定义:
export declare const ZodIssueCode: { invalid_type: "invalid_type"; invalid_literal: "invalid_literal"; custom: "custom"; invalid_union: "invalid_union"; invalid_union_discriminator: "invalid_union_discriminator"; invalid_enum_value: "invalid_enum_value"; unrecognized_keys: "unrecognized_keys"; invalid_arguments: "invalid_arguments"; invalid_return_type: "invalid_return_type"; invalid_date: "invalid_date"; invalid_string: "invalid_string"; too_small: "too_small"; too_big: "too_big"; invalid_intersection_types: "invalid_intersection_types"; not_multiple_of: "not_multiple_of"; not_finite: "not_finite"; };
解决方案
Zod没有单独的必填项IssueCode,必填字段缺失的错误会归类到invalid_type,此时issue.received的值为undefined,issue.expected为该字段预期的类型(如string、number等)。
只需在invalid_type分支中优先判断received是否为undefined,返回自定义必填提示即可,修改后的错误映射代码如下:
const customErrorMap: z.ZodErrorMap = (issue, ctx) => { switch (issue.code) { case z.ZodIssueCode.invalid_type: // 处理必填项缺失场景 if (issue.received === undefined) { return { message: '此字段为必填项' }; } // 原有类型不匹配判断逻辑 if (issue.expected === "string") { return { message: '请输入有效的字符串' }; } else if (issue.expected === "number") { return { message: '请输入有效的数字' }; } else { return { message: '类型不匹配' }; } case z.ZodIssueCode.custom: return { message: issue.message || '自定义错误' }; case z.ZodIssueCode.invalid_union: return { message: '无效的联合类型' }; case z.ZodIssueCode.invalid_enum_value: return { message: '无效的枚举值' }; case z.ZodIssueCode.unrecognized_keys: return { message: '存在未识别的字段' }; case z.ZodIssueCode.invalid_arguments: return { message: '无效的参数' }; case z.ZodIssueCode.invalid_return_type: return { message: '无效的返回类型' }; case z.ZodIssueCode.invalid_date: return { message: '无效的日期格式' }; case z.ZodIssueCode.invalid_string: return { message: '无效的字符串格式' }; case z.ZodIssueCode.too_small: return { message: '值过小' }; case z.ZodIssueCode.too_big: return { message: '值过大' }; case z.ZodIssueCode.invalid_intersection_types: return { message: '无效的交叉类型' }; case z.ZodIssueCode.not_multiple_of: return { message: '不是指定倍数' }; case z.ZodIssueCode.not_finite: return { message: '不是有限数值' }; default: return { message: ctx.defaultError }; } }
最后设置全局错误映射生效:
z.setErrorMap(customErrorMap);
这样就能统一处理所有必填字段的缺失提示,无需再逐个字段手动设置。
内容的提问来源于stack exchange,提问作者steve123
相关产品推荐
相关产品推荐

