react-hook-form/resolvers: One Adapter for Nineteen Validation Libraries
Validation resolvers: Yup, Zod, Superstruct, Joi, Vest, Class Validator, io-ts, Nope, computed-types, typanion, Ajv, TypeBox, ArkType, Valibot, effect-ts, VineJS and Standard Schema.
At a glance
- What is it?
- This package gives react-hook-form a single adapter for Yup, Zod, Joi, Vest, and fifteen other validation libraries. It standardizes how schemas plug into useForm, but the trade-offs show up in option handling and type inference.
- Who is it for?
- Adopt @hookform/resolvers if you already use react-hook-form and want to swap or mix validation libraries without rewriting your form logic. The package is thin, MIT-licensed, and the resolver comparison table in the README gives you a concrete basis for picking a library.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What This Resolver Package Actually Does
react-hook-form/resolvers solves a specific integration problem. react-hook-form needs a way to validate form values against an external schema, and each validation library has its own API. This package provides a uniform resolver function that wraps Yup, Zod, Joi, Vest, Superstruct, and fourteen other libraries. Instead of writing a custom validation function for each library, you import a named resolver, pass your schema, and hand it to useForm's resolver option. The intended user is a react-hook-form developer who already has a preferred schema library or needs to evaluate several. The package does not add new validation logic; it translates between react-hook-form's expected input and each library's validation call.
The Resolver API and Its Two Options
The core API is a single function signature: resolver(schema, schemaOptions?, resolverOptions?). The schema is your validation schema object. schemaOptions are passed through to the validation library itself. resolverOptions has two keys: mode, which can be 'async' or 'sync', and raw, a boolean. The default mode is 'async'. This matters because some validation libraries are synchronous by nature, and forcing them into async mode can add unnecessary overhead. The raw option likely controls whether the resolver passes raw form values or processed ones, though the README does not detail its effect. The API is deliberately small, which keeps the package lightweight, but it also means resolver-specific features are only available if the underlying library's schemaOptions can carry them.
Type Inference: The Comparison Table's Real Value
The README includes a comparison table that lists each resolver and whether it can infer values from the schema. Zod, Yup, ArkType, Valibot, TypeBox, and several others mark 'yes'. AJV, Joi, Vest, and a few others mark 'no'. This is not a cosmetic detail. When inference is supported, you can write useForm<Input, Context, Output>() and have the output type derived from the schema. The README shows an example with zodResolver where useForm({ resolver: zodResolver(schema) }) automatically infers the output type. Without inference, you must manually type the form values, which defeats part of the benefit of schema validation. The table also lists criteriaMode support. Most resolvers support both 'firstError' and 'all', but ArkType, computed-types, io-ts, Nope, Superstruct, and typanion only support 'firstError'. If you need to show all validation errors at once, those resolvers are the wrong choice.
Getting It Running: Install and First Example
Installation is straightforward. The README shows npm install @hookform/resolvers, with yarn, pnpm, and bun equivalents. You also need to install your chosen validation library separately. The quickstart examples are concrete. For Yup, you import yupResolver, define a yup schema, and pass it to useForm: useForm({ resolver: yupResolver(schema) }). For Zod, you import zodResolver and do the same. The examples show register and handleSubmit wiring exactly as you would with any react-hook-form form. One note: the Yup section warns against passing context via schemaOptions. It says schemaOptions.context is overridden by the form context, so you must pass context through useForm({ context }) instead. That is a real gotcha that could trip up developers migrating from direct Yup usage.
A Genuine Limitation: Default Values and Type Conflicts
The README includes a warning about Zod schemas that use .default(...). If a field has a default, it becomes optional on the schema's input type (z.input) but stays required on the output type (z.output). The default only fills in after validation. If you pass a single generic to useForm<T>, that pins both input and output to the same type, which conflicts with zodResolver because the resolver infers input and output separately. The README shows the workaround: useForm<z.input<typeof schema>, any, z.output<typeof schema>>. This is a concrete failure mode where the package's abstraction leaks. You need to understand Zod's input/output distinction to make it work. This is not a bug in the resolver; it is a consequence of combining two type systems, but it is the kind of friction that makes you wonder if the adapter saves enough time.
Maintenance and Upgrade Cost
The repository is actively maintained. The last push was August 17, 2026, with releases v5.9.0 and v5.9.1 in the same week. The package is published on npm as @hookform/resolvers, and the README links to react-hook-form's official resolver documentation. The license is MIT, which means you can use it in commercial projects without permissive licensing concerns, though this is not legal advice. The upgrade cost is low because the package is a thin wrapper. When a new validation library version changes its API, the resolver package needs an update, but you can pin your validation library version to avoid breakage. The active release cadence suggests the maintainers are responsive to upstream changes, but it also means you should watch for breaking changes between minor versions.
Alternatives: Writing Your Own Resolver or Skipping Adapters
The obvious alternative is to write a custom resolver function for react-hook-form. The README explicitly says you can write your own logic if you are not using a library. That gives you full control over validation flow, error formatting, and type inference. The cost is that you must implement the resolver interface correctly, including handling async and sync modes, and you lose the convenience of a tested adapter. Another alternative is to use a validation library that has first-class react-hook-form integration, but that is rare; most libraries rely on adapters like this one. The real difference is that @hookform/resolvers centralizes the integration logic, so you do not have to maintain it yourself. If you have a simple form with one validation library, writing a custom resolver might be less overhead than adding a dependency. If you have multiple forms using different libraries, the adapter package becomes more attractive.
Editorial conclusion
Adopt @hookform/resolvers if you already use react-hook-form and want to swap or mix validation libraries without rewriting your form logic. The package is thin, MIT-licensed, and the resolver comparison table in the README gives you a concrete basis for picking a library. Do not use it if your schema library requires resolver-specific options that the adapter does not expose, or if you need criteriaMode 'all' from a resolver that only supports 'firstError'. Before committing, verify that your chosen resolver supports the mode you need, check whether it can infer output types from your schema, and confirm that your validation library's context passing works through useForm, not through schemaOptions.
Community notes