You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Zod的refine方法中设置错误信息而非抛出错误?

问题:Zod refine方法中如何设置自定义错误信息而非抛出错误导致应用退出?

我有如下Zod schema:

const createApSchema = z
  .object({
    name: z.string().min(1).max(32),
    isActive: z.boolean().default(true),
    description: z.string().max(200).optional(),
    ip: z.string().refine(validator.isIP),
    accessMode: AccessModeEnum,
    apiUsername: z.string().optional(),
    apiPassword: z.string().optional(),
    apiVersion: ApiVersionEnum,
    community: z.string().optional(),
  })
  .refine((data) => {
    // check to see if AP type is snmp to force the community field
    const isSnmp = data.accessMode !== AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi]
    if (isSnmp && !data.community) throw new Error('community string is required!')
    // check to see if AP type is mikrotik to force the api credentials fields
    if (!isSnmp && (!data.apiUsername || !data.apiPassword)) throw new Error('api username and password are required!')
    if (!isSnmp && !data.apiVersion) throw new Error('api version is required!')
    return true
  })

规则要求:当accessMode属性选择"mikrotikApi"值时,apiUsername、apiPassword和apiVersion字段为必填;若选择"snmp"等其他值,则community字段为必填。

当前代码可实现验证,但在schema的refine方法中通过抛出错误提示验证失败会导致应用退出,我希望设置错误信息以便自行处理,而非让应用退出。


解决方案

Zod的refine方法支持传入第二个参数配置对象,通过message字段指定自定义错误信息,同时将验证逻辑改为返回false触发错误(而非抛出Error)。另外,将多个验证规则拆分为独立的refine调用,能让错误信息更清晰,也便于后续维护。

修改后的代码如下:

const createApSchema = z
  .object({
    name: z.string().min(1).max(32),
    isActive: z.boolean().default(true),
    description: z.string().max(200).optional(),
    ip: z.string().refine(validator.isIP),
    accessMode: AccessModeEnum,
    apiUsername: z.string().optional(),
    apiPassword: z.string().optional(),
    apiVersion: ApiVersionEnum,
    community: z.string().optional(),
  })
  // 验证SNMP模式下community必填
  .refine(
    (data) => {
      const isSnmp = data.accessMode !== AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi];
      return !isSnmp || !!data.community;
    },
    { 
      message: 'community string is required!',
      path: ['community'] // 将错误关联到community字段,便于定位
    }
  )
  // 验证mikrotikApi模式下apiUsername和apiPassword必填
  .refine(
    (data) => {
      const isMikrotik = data.accessMode === AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi];
      return !isMikrotik || (!!data.apiUsername && !!data.apiPassword);
    },
    { 
      message: 'api username and password are required!',
      path: ['apiUsername', 'apiPassword'] // 关联到对应字段
    }
  )
  // 验证mikrotikApi模式下apiVersion必填
  .refine(
    (data) => {
      const isMikrotik = data.accessMode === AccessModeEnumMap[AccessModeEnum.enum.mikrotikApi];
      return !isMikrotik || !!data.apiVersion;
    },
    { 
      message: 'api version is required!',
      path: ['apiVersion'] // 关联到对应字段
    }
  );

使用示例

调用safeParse方法获取验证结果,该方法不会抛出错误,而是返回包含验证状态和信息的对象:

const formData = {
  // 你的表单数据
};

const validationResult = createApSchema.safeParse(formData);

if (!validationResult.success) {
  // 提取所有错误信息自行处理
  const errorList = validationResult.error.issues.map(issue => {
    return {
      field: issue.path.join('.'),
      message: issue.message
    };
  });
  
  console.log('验证失败:', errorList);
  // 这里可以将错误信息展示给用户或进行其他业务处理
}

内容的提问来源于stack exchange,提问作者Islam Y-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 00:40:22