首页
/ Zod项目中预处理函数导致验证被跳过的Bug分析

Zod项目中预处理函数导致验证被跳过的Bug分析

2025-05-03 15:43:03作者:何举烈Damon

Zod是一个流行的TypeScript模式验证库,最近在3.22.0版本升级中出现了一个关于预处理(preprocess)函数的Bug,导致部分字段验证被意外跳过。

问题现象

当使用预处理函数时,某些字段的验证错误不会出现在最终的错误对象中。具体表现为:

  1. 如果对象中有多个字段,其中一些使用预处理函数而另一些不使用
  2. 当这些字段都验证失败时
  3. 只有不使用预处理函数的字段错误会被报告

示例代码

const schema = z.object({
  foo: z.string().min(4),  // 不使用预处理
  bar: z.preprocess((val) => val, z.string().min(4)),  // 使用预处理
});

const values = {
  foo: "abc",  // 不足4个字符
  bar: "abc",  // 不足4个字符
};

在3.22.0版本之前,这个验证会正确报告foo和bar两个字段的错误。但在3.22.x版本中,只会报告foo字段的错误。

技术分析

这个Bug的出现与Zod内部验证流程的改变有关。预处理函数在3.22.0版本中的处理方式发生了变化,导致验证流程在某些情况下提前终止。

根本原因

  1. 验证流程中断:预处理函数的加入可能改变了验证的错误收集机制
  2. 执行顺序影响:当多个字段都使用预处理时,错误的出现似乎与字段定义的顺序有关
  3. 错误收集不完整:验证系统没有完整收集所有失败字段的错误信息

临时解决方案

在官方修复此Bug之前,可以使用以下替代方案:

const schema = z.object({
  foo: z.string().min(4),
  bar: z.any().transform(val => val).pipe(z.string().min(4))
});

这种使用transform和pipe组合的方式可以绕过预处理函数的问题,同时保持相同的功能。

影响范围

这个Bug影响所有使用预处理函数进行复杂验证的场景,特别是:

  1. 对象中有混合使用预处理和非预处理字段的情况
  2. 需要收集所有验证错误而不仅仅是第一个错误的场景
  3. 依赖完整错误信息进行表单验证或其他用户反馈的系统

最佳实践建议

  1. 在升级到3.22.x版本时,应特别检查所有使用预处理函数的验证逻辑
  2. 对于关键验证场景,考虑暂时回退到3.21.4版本
  3. 或者使用上述的transform+pipe组合作为替代方案
  4. 等待官方修复版本发布后再进行全面升级

这个Bug已经被Zod团队确认,并标记为重复问题,说明开发团队已经注意到此问题并可能在后续版本中修复。开发者在使用预处理功能时应保持关注官方更新。

登录后查看全文
热门项目推荐
相关项目推荐