库 / SDK
react-hook-form/resolvers avatar
react-hook-form/resolvers

react-hook-form/resolvers:把二十种校验库塞进一个 useForm 的适配层

验证解析器:Yup、Zod、Superstruct、Joi、Vest、Class Validator、io-ts、Nope、计算类型、typanion、Ajv、TypeBox、ArkType、Valibot、effect-ts、VineJS 和 Standard Schema。

2,258 个 Star215 个 ForkTypeScriptMIT

秒懂

它是什么?
这个项目为 React Hook Form 提供了统一的 resolver 接口,让 Yup、Zod、Joi 等二十种校验库可以即插即用。本文拆解它的适配机制、类型推断差异和实际使用中的坑。
适合谁用?
如果你的项目已经在用 React Hook Form,并且想换掉手写的校验逻辑,或者需要在 Yup、Zod 之间迁移,这个包值得用。它解决的是适配层问题,不替你选校验库。
能商用吗?
可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
还在维护吗?
在维护。仓库最近一次提交在 30 天前。
用什么语言写的?
主要是 TypeScript(依据 GitHub 的语言统计)。

以上回答依据项目的 GitHub 数据(最近同步于 2026年9月14日)和我们的分析,不构成法律意见。

开源项目深度解析

它解决的是 React Hook Form 的校验接入问题

React Hook Form 本身不绑定任何校验库。它把校验逻辑留给用户,通过 resolver 这个函数接口接收外部校验结果。但每个校验库的 API 和错误格式都不一样,直接对接意味着每个项目都要写一遍适配代码。react-hook-form/resolvers 把这些适配代码集中到一个包里,目前支持 20 种库,包括 Yup、Zod、Joi、Ajv、Valibot、ArkType 等。它的目标用户很明确:已经在用 React Hook Form,并且希望用 schema 驱动校验的 TypeScript 开发者。如果你不用 React Hook Form,这个包毫无用处。

resolver 的接口设计:schema、schemaOptions 和 resolverOptions

每个 resolver 都是一个函数,接收三个参数。第一个是 schema 对象,第二个是传给校验库本身的选项,第三个是 resolver 自己的选项。resolverOptions 里只有两个键:mode 和 raw。mode 默认是 async,也可以设为 sync。raw 决定传给校验库的是原始表单值还是经过 React Hook Form 转换后的值。这个三层设计让适配层保持薄,它不重写校验逻辑,只是把 React Hook Form 的字段值喂给校验库,再把校验库的错误对象转成 React Hook Form 认识的格式。文档里特别警告了一件事:Yup 的 context 不能通过 schemaOptions 传,必须用 useForm 的 context 参数,因为 schemaOptions.context 会被表单 context 覆盖。这种细节如果不看文档,很容易踩坑。

类型推断:不是所有 resolver 都能从 schema 推出类型

README 里有一张对比表,列出了每个 resolver 是否支持从 schema 推断值类型。Zod、Yup、Valibot、ArkType 这些支持,Joi、Ajv、Vest 不支持。这意味着用 Joi 或 Ajv 时,你需要手动给 useForm 传泛型参数。对于支持推断的 resolver,比如 zodResolver,它内部会根据 schema 的 input 和 output 类型分别推断。文档给出了一个例子:如果 schema 里某个字段用了 .default(),这个字段在 input 类型里是可选的,但在 output 类型里是必填的。如果只给 useForm 传一个泛型,比如 useForm<T>,那 input 和 output 被钉成同一个类型,会和 zodResolver 的推断冲突。解决办法是显式传三个泛型:useForm<z.input<typeof schema>, any, z.output<typeof schema>>。这个细节很容易被忽略,但会导致类型错误。

安装和基本用法:一行代码接入 Zod

安装命令很简单:npm install @hookform/resolvers,然后按需安装你选的校验库,比如 npm install zod。用法上,把 resolver 传给 useForm 的配置对象即可。README 里 Zod 的例子是这样:先定义 schema,然后 useForm({ resolver: zodResolver(schema) }),之后 register 和 handleSubmit 照常使用。错误信息通过 formState.errors 获取,比如 errors.name?.message。整个过程不需要手写任何校验函数。如果你用 Yup,需要把 schema 写成 yup.object().shape({...}),然后传给 yupResolver。这个模式对所有 resolver 都一样,只是 schema 的写法随库而异。

criteriaMode 的差异:有些库只能报第一个错误

对比表里还有一列是 criteriaMode,它决定 React Hook Form 是返回第一个错误还是所有错误。Zod、Yup、Joi、Valibot 支持 firstError 和 all 两种模式,但 ArkType、computed-types、io-ts、Nope、Superstruct、typanion 只支持 firstError。这意味着如果你需要一次显示所有字段的校验错误,比如注册表单每个字段都标红,那 ArkType 这类库就做不到,至少通过 resolver 不行。这不是 resolver 的问题,是底层库的错误聚合能力有限。选库之前先确认这一点,否则后期要改校验库,代价不小。

维护和升级成本:跟着 React Hook Form 走

这个包是 React Hook Form 官方生态的一部分,主页链接指向 react-hook-form.com 的文档。它跟随 React Hook Form 的版本迭代,最近一次提交在 2026 年 8 月,说明还在活跃维护。许可证是 MIT,可以自由使用和修改。升级成本主要来自两方面:一是校验库本身升级,比如 Zod 4 的导入路径变成了 'zod/v4',resolver 的导入路径不变,但 schema 的写法可能变了;二是 React Hook Form 升级时,resolver 的接口如果调整,需要同步升级。好在 resolver 的 API 很薄,schema 和 schemaOptions 都是透传,大部分升级只是重新编译验证。

替代方案:自己写适配器和不用 resolver

不用的替代方案有两个。第一个是 React Hook Form 自带的 register 验证规则,比如 required、min、max,但那只适合简单校验,无法处理跨字段逻辑或异步校验。第二个是自己写一个 resolver,React Hook Form 的 resolver 接口是公开的,你只需要返回 { values, errors } 这样的结构。自己写的优势是零依赖,完全控制错误格式,但代价是要为每个校验库写一遍,而且容易漏掉类型推断。相比之下,这个包的价值在于它已经处理了 20 种库的边界情况,比如 Zod 的 default 字段类型冲突。如果你的校验需求超出内置规则,又不想维护适配层,这个包是省事的选择。

编辑结论

如果你的项目已经在用 React Hook Form,并且想换掉手写的校验逻辑,或者需要在 Yup、Zod 之间迁移,这个包值得用。它解决的是适配层问题,不替你选校验库。谁不该用:表单只有三五个字段、校验规则简单的人,直接写 register 的 validate 回调就够了,多引入一层依赖反而增加体积。谁该用:表单结构复杂、需要 schema 驱动校验、或者团队已经熟悉某个校验库的人。先验证三件事:你选的 resolver 是否支持 criteriaMode 的 all 模式,这决定了错误是只显示第一个还是全部;确认你的校验库版本是否在支持的范围内,比如 Zod 3 和 Zod 4 的导入路径不同;检查 schema 里有没有 .default() 字段,这会影响 TypeScript 泛型推断,需要显式传 input 和 output 类型。

官方来源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
社区笔记

社区笔记