Gathering detailed insights and metrics for @hookform/resolvers
Gathering detailed insights and metrics for @hookform/resolvers
Gathering detailed insights and metrics for @hookform/resolvers
Gathering detailed insights and metrics for @hookform/resolvers
@dudeofawesome/hookform-resolvers
React Hook Form validation resolvers: Yup, Joi, Superstruct, Zod, Vest, Class Validator, io-ts, Nope, computed-types, TypeBox, arktype, Typanion, Effect-TS and VineJS
@psymorias/hookform-resolvers-ajv
React Hook Form validation resolvers: Yup, Joi, Superstruct, Ajv and etc.
react-hook-formify
A smart wrapper around react-hook-form + zustand
sharpcodes19-form
react-hook-forms support for heroui
📋 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
npm install @hookform/resolvers
Typescript
Module System
Node Version
NPM Version
97.5
Supply Chain
85.1
Quality
94.5
Maintenance
100
Vulnerability
100
License
TypeScript (98.61%)
Shell (1.11%)
JavaScript (0.28%)
Total Downloads
464,379,048
Last Day
807,665
Last Week
9,990,850
Last Month
39,222,816
Last Year
267,030,940
MIT License
2,058 Stars
366 Commits
195 Forks
12 Watchers
4 Branches
67 Contributors
Updated on Jul 30, 2025
Latest Version
5.2.1
Package Id
@hookform/resolvers@5.2.1
Unpacked Size
966.63 kB
Size
116.45 kB
File Count
399
NPM Version
10.9.3
Node Version
20.19.4
Published on
Jul 29, 2025
Cumulative downloads
Total Downloads
Last Day
19.2%
807,665
Compared to previous day
Last Week
6.9%
9,990,850
Compared to previous week
Last Month
5.2%
39,222,816
Compared to previous month
Last Year
141.4%
267,030,940
Compared to previous year
1
1
50
Performant, flexible and extensible forms with easy to use validation.
This function allows you to use any external validation library such as Yup, Zod, Joi, Vest, Ajv and many others. The goal is to make sure you can seamlessly integrate whichever validation library you prefer. If you're not using a library, you can always write your own logic to validate your forms.
Install your preferred validation library alongside @hookform/resolvers
.
npm install @hookform/resolvers # npm
yarn add @hookform/resolvers # yarn
pnpm install @hookform/resolvers # pnpm
bun install @hookform/resolvers # bun
resolver | Infer values from schema | criteriaMode |
---|---|---|
AJV | ❌ | firstError | all |
Arktype | ✅ | firstError |
class-validator | ✅ | firstError | all |
computed-types | ✅ | firstError |
Effect | ✅ | firstError | all |
fluentvalidation-ts | ❌ | firstError |
io-ts | ✅ | firstError |
joi | ❌ | firstError | all |
Nope | ❌ | firstError |
Standard Schema | ✅ | firstError | all |
Superstruct | ✅ | firstError |
typanion | ✅ | firstError |
typebox | ✅ | firstError | all |
typeschema | ❌ | firstError | all |
valibot | ✅ | firstError | all |
vest | ❌ | firstError | all |
vine | ✅ | firstError | all |
yup | ✅ | firstError | all |
zod | ✅ | firstError | all |
Most of the resolvers can infer the output type from the schema. See comparison table for more details.
1useForm<Input, Context, Output>()
Example:
1import { useForm } from 'react-hook-form'; 2import { zodResolver } from '@hookform/resolvers/zod'; 3import { z } from 'zod'; // or 'zod/v4' 4 5const schema = z.object({ 6 id: z.number(), 7}); 8 9// Automatically infers the output type from the schema 10useForm({ 11 resolver: zodResolver(schema), 12}); 13 14// Force the output type 15useForm<z.input<typeof schema>, any, z.output<typeof schema>>({ 16 resolver: zodResolver(schema), 17});
type Options = {
mode: 'async' | 'sync',
raw?: boolean
}
resolver(schema: object, schemaOptions?: object, resolverOptions: Options)
type | Required | Description | |
---|---|---|---|
schema | object | ✓ | validation schema |
schemaOptions | object | validation library schema options | |
resolverOptions | object | resolver options, async is the default mode |
Dead simple Object schema validation.
1import { useForm } from 'react-hook-form'; 2import { yupResolver } from '@hookform/resolvers/yup'; 3import * as yup from 'yup'; 4 5const schema = yup 6 .object() 7 .shape({ 8 name: yup.string().required(), 9 age: yup.number().required(), 10 }) 11 .required(); 12 13const App = () => { 14 const { register, handleSubmit } = useForm({ 15 resolver: yupResolver(schema), 16 }); 17 18 return ( 19 <form onSubmit={handleSubmit((d) => console.log(d))}> 20 <input {...register('name')} /> 21 <input type="number" {...register('age')} /> 22 <input type="submit" /> 23 </form> 24 ); 25};
TypeScript-first schema validation with static type inference
⚠️ Example below uses the
valueAsNumber
, which requiresreact-hook-form
v6.12.0 (released Nov 28, 2020) or later.
1import { useForm } from 'react-hook-form'; 2import { zodResolver } from '@hookform/resolvers/zod'; 3import { z } from 'zod'; // or 'zod/v4' 4 5const schema = z.object({ 6 name: z.string().min(1, { message: 'Required' }), 7 age: z.number().min(10), 8}); 9 10const App = () => { 11 const { 12 register, 13 handleSubmit, 14 formState: { errors }, 15 } = useForm({ 16 resolver: zodResolver(schema), 17 }); 18 19 return ( 20 <form onSubmit={handleSubmit((d) => console.log(d))}> 21 <input {...register('name')} /> 22 {errors.name?.message && <p>{errors.name?.message}</p>} 23 <input type="number" {...register('age', { valueAsNumber: true })} /> 24 {errors.age?.message && <p>{errors.age?.message}</p>} 25 <input type="submit" /> 26 </form> 27 ); 28};
A simple and composable way to validate data in JavaScript (or TypeScript).
1import { useForm } from 'react-hook-form'; 2import { superstructResolver } from '@hookform/resolvers/superstruct'; 3import { object, string, number } from 'superstruct'; 4 5const schema = object({ 6 name: string(), 7 age: number(), 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: superstructResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('name')} /> 18 <input type="number" {...register('age', { valueAsNumber: true })} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
The most powerful data validation library for JS.
1import { useForm } from 'react-hook-form'; 2import { joiResolver } from '@hookform/resolvers/joi'; 3import Joi from 'joi'; 4 5const schema = Joi.object({ 6 name: Joi.string().required(), 7 age: Joi.number().required(), 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: joiResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('name')} /> 18 <input type="number" {...register('age')} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
Vest 🦺 Declarative Validation Testing.
1import { useForm } from 'react-hook-form'; 2import { vestResolver } from '@hookform/resolvers/vest'; 3import { create, test, enforce } from 'vest'; 4 5const validationSuite = create((data = {}) => { 6 test('username', 'Username is required', () => { 7 enforce(data.username).isNotEmpty(); 8 }); 9 10 test('password', 'Password is required', () => { 11 enforce(data.password).isNotEmpty(); 12 }); 13}); 14 15const App = () => { 16 const { register, handleSubmit, errors } = useForm({ 17 resolver: vestResolver(validationSuite), 18 }); 19 20 return ( 21 <form onSubmit={handleSubmit((data) => console.log(data))}> 22 <input {...register('username')} /> 23 <input type="password" {...register('password')} /> 24 <input type="submit" /> 25 </form> 26 ); 27};
Decorator-based property validation for classes.
⚠️ Remember to add these options to your
tsconfig.json
!
"strictPropertyInitialization": false,
"experimentalDecorators": true
1import { useForm } from 'react-hook-form'; 2import { classValidatorResolver } from '@hookform/resolvers/class-validator'; 3import { Length, Min, IsEmail } from 'class-validator'; 4 5class User { 6 @Length(2, 30) 7 username: string; 8 9 @IsEmail() 10 email: string; 11} 12 13const resolver = classValidatorResolver(User); 14 15const App = () => { 16 const { 17 register, 18 handleSubmit, 19 formState: { errors }, 20 } = useForm<User>({ resolver }); 21 22 return ( 23 <form onSubmit={handleSubmit((data) => console.log(data))}> 24 <input type="text" {...register('username')} /> 25 {errors.username && <span>{errors.username.message}</span>} 26 <input type="text" {...register('email')} /> 27 {errors.email && <span>{errors.email.message}</span>} 28 <input type="submit" value="Submit" /> 29 </form> 30 ); 31};
Validate your data with powerful decoders.
1import React from 'react'; 2import { useForm } from 'react-hook-form'; 3import { ioTsResolver } from '@hookform/resolvers/io-ts'; 4import t from 'io-ts'; 5// you don't have to use io-ts-types, but it's very useful 6import tt from 'io-ts-types'; 7 8const schema = t.type({ 9 username: t.string, 10 age: tt.NumberFromString, 11}); 12 13const App = () => { 14 const { register, handleSubmit } = useForm({ 15 resolver: ioTsResolver(schema), 16 }); 17 18 return ( 19 <form onSubmit={handleSubmit((d) => console.log(d))}> 20 <input {...register('username')} /> 21 <input type="number" {...register('age')} /> 22 <input type="submit" /> 23 </form> 24 ); 25}; 26 27export default App;
A small, simple, and fast JS validator
1import { useForm } from 'react-hook-form'; 2import { nopeResolver } from '@hookform/resolvers/nope'; 3import Nope from 'nope-validator'; 4 5const schema = Nope.object().shape({ 6 name: Nope.string().required(), 7 age: Nope.number().required(), 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: nopeResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('name')} /> 18 <input type="number" {...register('age')} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
TypeScript-first schema validation with static type inference
1import { useForm } from 'react-hook-form'; 2import { computedTypesResolver } from '@hookform/resolvers/computed-types'; 3import Schema, { number, string } from 'computed-types'; 4 5const schema = Schema({ 6 username: string.min(1).error('username field is required'), 7 age: number, 8}); 9 10const App = () => { 11 const { 12 register, 13 handleSubmit, 14 formState: { errors }, 15 } = useForm({ 16 resolver: computedTypesResolver(schema), 17 }); 18 19 return ( 20 <form onSubmit={handleSubmit((d) => console.log(d))}> 21 <input {...register('name')} /> 22 {errors.name?.message && <p>{errors.name?.message}</p>} 23 <input type="number" {...register('age', { valueAsNumber: true })} /> 24 {errors.age?.message && <p>{errors.age?.message}</p>} 25 <input type="submit" /> 26 </form> 27 ); 28};
Static and runtime type assertion library with no dependencies
1import { useForm } from 'react-hook-form'; 2import { typanionResolver } from '@hookform/resolvers/typanion'; 3import * as t from 'typanion'; 4 5const isUser = t.isObject({ 6 username: t.applyCascade(t.isString(), [t.hasMinLength(1)]), 7 age: t.applyCascade(t.isNumber(), [ 8 t.isInteger(), 9 t.isInInclusiveRange(1, 100), 10 ]), 11}); 12 13const App = () => { 14 const { 15 register, 16 handleSubmit, 17 formState: { errors }, 18 } = useForm({ 19 resolver: typanionResolver(isUser), 20 }); 21 22 return ( 23 <form onSubmit={handleSubmit((d) => console.log(d))}> 24 <input {...register('name')} /> 25 {errors.name?.message && <p>{errors.name?.message}</p>} 26 <input type="number" {...register('age')} /> 27 {errors.age?.message && <p>{errors.age?.message}</p>} 28 <input type="submit" /> 29 </form> 30 ); 31};
The fastest JSON validator for Node.js and browser
1import { useForm } from 'react-hook-form'; 2import { ajvResolver } from '@hookform/resolvers/ajv'; 3 4// must use `minLength: 1` to implement required field 5const schema = { 6 type: 'object', 7 properties: { 8 username: { 9 type: 'string', 10 minLength: 1, 11 errorMessage: { minLength: 'username field is required' }, 12 }, 13 password: { 14 type: 'string', 15 minLength: 1, 16 errorMessage: { minLength: 'password field is required' }, 17 }, 18 }, 19 required: ['username', 'password'], 20 additionalProperties: false, 21}; 22 23const App = () => { 24 const { 25 register, 26 handleSubmit, 27 formState: { errors }, 28 } = useForm({ 29 resolver: ajvResolver(schema), 30 }); 31 32 return ( 33 <form onSubmit={handleSubmit((data) => console.log(data))}> 34 <input {...register('username')} /> 35 {errors.username && <span>{errors.username.message}</span>} 36 <input {...register('password')} /> 37 {errors.password && <span>{errors.password.message}</span>} 38 <button type="submit">submit</button> 39 </form> 40 ); 41};
JSON Schema Type Builder with Static Type Resolution for TypeScript
ValueCheck
1import { useForm } from 'react-hook-form'; 2import { typeboxResolver } from '@hookform/resolvers/typebox'; 3import { Type } from '@sinclair/typebox'; 4 5const schema = Type.Object({ 6 username: Type.String({ minLength: 1 }), 7 password: Type.String({ minLength: 1 }), 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: typeboxResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('username')} /> 18 <input type="password" {...register('password')} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
TypeCompiler
A high-performance JIT of TypeBox
, read more
1import { useForm } from 'react-hook-form'; 2import { typeboxResolver } from '@hookform/resolvers/typebox'; 3import { Type } from '@sinclair/typebox'; 4import { TypeCompiler } from '@sinclair/typebox/compiler'; 5 6const schema = Type.Object({ 7 username: Type.String({ minLength: 1 }), 8 password: Type.String({ minLength: 1 }), 9}); 10 11const typecheck = TypeCompiler.Compile(schema); 12 13const App = () => { 14 const { register, handleSubmit } = useForm({ 15 resolver: typeboxResolver(typecheck), 16 }); 17 18 return ( 19 <form onSubmit={handleSubmit((d) => console.log(d))}> 20 <input {...register('username')} /> 21 <input type="password" {...register('password')} /> 22 <input type="submit" /> 23 </form> 24 ); 25};
TypeScript's 1:1 validator, optimized from editor to runtime
1import { useForm } from 'react-hook-form'; 2import { arktypeResolver } from '@hookform/resolvers/arktype'; 3import { type } from 'arktype'; 4 5const schema = type({ 6 username: 'string>1', 7 password: 'string>1', 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: arktypeResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('username')} /> 18 <input type="password" {...register('password')} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
The modular and type safe schema library for validating structural data
1import { useForm } from 'react-hook-form'; 2import { valibotResolver } from '@hookform/resolvers/valibot'; 3import * as v from 'valibot'; 4 5const schema = v.object({ 6 username: v.pipe( 7 v.string('username is required'), 8 v.minLength(3, 'Needs to be at least 3 characters'), 9 v.endsWith('cool', 'Needs to end with `cool`'), 10 ), 11 password: v.string('password is required'), 12}); 13 14const App = () => { 15 const { register, handleSubmit } = useForm({ 16 resolver: valibotResolver(schema), 17 }); 18 19 return ( 20 <form onSubmit={handleSubmit((d) => console.log(d))}> 21 <input {...register('username')} /> 22 <input type="password" {...register('password')} /> 23 <input type="submit" /> 24 </form> 25 ); 26};
Universal adapter for schema validation, compatible with any validation library
1import { useForm } from 'react-hook-form'; 2import { typeschemaResolver } from '@hookform/resolvers/typeschema'; 3import { z } from 'zod'; 4 5// Use your favorite validation library 6const schema = z.object({ 7 username: z.string().min(1, { message: 'Required' }), 8 password: z.number().min(1, { message: 'Required' }), 9}); 10 11const App = () => { 12 const { register, handleSubmit } = useForm({ 13 resolver: typeschemaResolver(schema), 14 }); 15 16 return ( 17 <form onSubmit={handleSubmit((d) => console.log(d))}> 18 <input {...register('username')} /> 19 <input type="password" {...register('password')} /> 20 <input type="submit" /> 21 </form> 22 ); 23};
A powerful TypeScript framework that provides a fully-fledged functional effect system with a rich standard library.
1import React from 'react'; 2import { useForm } from 'react-hook-form'; 3import { effectTsResolver } from '@hookform/resolvers/effect-ts'; 4import { Schema } from 'effect'; 5 6const schema = Schema.Struct({ 7 username: Schema.String.pipe( 8 Schema.nonEmptyString({ message: () => 'username required' }), 9 ), 10 password: Schema.String.pipe( 11 Schema.nonEmptyString({ message: () => 'password required' }), 12 ), 13}); 14 15type FormData = typeof schema.Type; 16 17interface Props { 18 onSubmit: (data: FormData) => void; 19} 20 21function TestComponent({ onSubmit }: Props) { 22 const { 23 register, 24 handleSubmit, 25 formState: { errors }, 26 // provide generic if TS has issues inferring types 27 } = useForm<FormData>({ 28 resolver: effectTsResolver(schema), 29 }); 30 31 return ( 32 <form onSubmit={handleSubmit(onSubmit)}> 33 <input {...register('username')} /> 34 {errors.username && <span role="alert">{errors.username.message}</span>} 35 36 <input {...register('password')} /> 37 {errors.password && <span role="alert">{errors.password.message}</span>} 38 39 <button type="submit">submit</button> 40 </form> 41 ); 42}
VineJS is a form data validation library for Node.js
1import { useForm } from 'react-hook-form'; 2import { vineResolver } from '@hookform/resolvers/vine'; 3import vine from '@vinejs/vine'; 4 5const schema = vine.compile( 6 vine.object({ 7 username: vine.string().minLength(1), 8 password: vine.string().minLength(1), 9 }), 10); 11 12const App = () => { 13 const { register, handleSubmit } = useForm({ 14 resolver: vineResolver(schema), 15 }); 16 17 return ( 18 <form onSubmit={handleSubmit((d) => console.log(d))}> 19 <input {...register('username')} /> 20 {errors.username && <span role="alert">{errors.username.message}</span>} 21 <input {...register('password')} /> 22 {errors.password && <span role="alert">{errors.password.message}</span>} 23 <button type="submit">submit</button> 24 </form> 25 ); 26};
A TypeScript-first library for building strongly-typed validation rules
1import { useForm } from 'react-hook-form'; 2import { fluentValidationResolver } from '@hookform/resolvers/fluentvalidation-ts'; 3import { Validator } from 'fluentvalidation-ts'; 4 5class FormDataValidator extends Validator<FormData> { 6 constructor() { 7 super(); 8 9 this.ruleFor('username') 10 .notEmpty() 11 .withMessage('username is a required field'); 12 this.ruleFor('password') 13 .notEmpty() 14 .withMessage('password is a required field'); 15 } 16} 17 18const App = () => { 19 const { register, handleSubmit } = useForm({ 20 resolver: fluentValidationResolver(new FormDataValidator()), 21 }); 22 23 return ( 24 <form onSubmit={handleSubmit((d) => console.log(d))}> 25 <input {...register('username')} /> 26 {errors.username && <span role="alert">{errors.username.message}</span>} 27 <input {...register('password')} /> 28 {errors.password && <span role="alert">{errors.password.message}</span>} 29 <button type="submit">submit</button> 30 </form> 31 ); 32};
A standard interface for TypeScript schema validation libraries
Example zod
1import { useForm } from 'react-hook-form'; 2import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'; 3import { z } from 'zod'; 4 5const schema = z.object({ 6 name: z.string().min(1, { message: 'Required' }), 7 age: z.number().min(10), 8}); 9 10const App = () => { 11 const { 12 register, 13 handleSubmit, 14 formState: { errors }, 15 } = useForm({ 16 resolver: standardSchemaResolver(schema), 17 }); 18 19 return ( 20 <form onSubmit={handleSubmit((d) => console.log(d))}> 21 <input {...register('name')} /> 22 {errors.name?.message && <p>{errors.name?.message}</p>} 23 <input type="number" {...register('age', { valueAsNumber: true })} /> 24 {errors.age?.message && <p>{errors.age?.message}</p>} 25 <input type="submit" /> 26 </form> 27 ); 28};
Example arkType
1import { useForm } from 'react-hook-form'; 2import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'; 3import { type } from 'arktype'; 4 5const schema = type({ 6 username: 'string>1', 7 password: 'string>1', 8}); 9 10const App = () => { 11 const { register, handleSubmit } = useForm({ 12 resolver: standardSchemaResolver(schema), 13 }); 14 15 return ( 16 <form onSubmit={handleSubmit((d) => console.log(d))}> 17 <input {...register('username')} /> 18 <input type="password" {...register('password')} /> 19 <input type="submit" /> 20 </form> 21 ); 22};
Thanks go to all our backers! [Become a backer].
Thanks go to these wonderful people! [Become a contributor].
No vulnerabilities found.