MCPcopy Index your code
hub / github.com/react-hook-form/resolvers

github.com/react-hook-form/resolvers @v5.4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v5.4.0 ↗ · + Follow
183 symbols 724 edges 144 files 1 documented · 1% 250 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README
    <a href="https://react-hook-form.com" title="React Hook Form - Simple React forms validation">
        <img src="https://raw.githubusercontent.com/bluebill1049/react-hook-form/master/docs/logo.png" alt="React Hook Form Logo - React hook custom hook for form validation" />
    </a>

Performant, flexible and extensible forms with easy to use validation.

npm downloads npm npm

React Hook Form Resolvers

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

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 Comparison

| resolver | Infer values

from schema | criteriaMode | |---|---|---| | AJV | ❌ | firstError \| all | | ata-validator | ❌ | 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 |

TypeScript

Most of the resolvers can infer the output type from the schema. See comparison table for more details.

useForm<Input, Context, Output>()

Example:

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod'; // or 'zod/v4'

const schema = z.object({
  id: z.number(),
});

// Automatically infers the output type from the schema
useForm({
  resolver: zodResolver(schema),
});

// Force the output type
useForm<z.input<typeof schema>, any, z.output<typeof schema>>({
  resolver: zodResolver(schema),
});

Links

Supported resolvers

API

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

Quickstart

Yup

Dead simple Object schema validation.

npm

⚠️ Pass context via useForm({ context }), not via yupResolver's schemaOptions. schemaOptions.context is overridden by the form context, so use the useForm context object instead.

```typescript jsx // Correct useForm({ resolver: yupResolver(schema), context: { foo: true }, });

// Avoid - schemaOptions.context will be ignored/overridden yupResolver(schema, { context: { foo: true } });


```typescript jsx
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';

const schema = yup
  .object()
  .shape({
    name: yup.string().required(),
    age: yup.number().required(),
  })
  .required();

const App = () => {
  const { register, handleSubmit } = useForm({
    resolver: yupResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      <input type="number" {...register('age')} />
      <input type="submit" />
    </form>
  );
};

Zod

TypeScript-first schema validation with static type inference

npm

⚠️ Example below uses the valueAsNumber, which requires react-hook-form v6.12.0 (released Nov 28, 2020) or later.

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod'; // or 'zod/v4'

const schema = z.object({
  name: z.string().min(1, { message: 'Required' }),
  age: z.number().min(10),
});

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      {errors.name?.message && 

{errors.name?.message}

}
      <input type="number" {...register('age', { valueAsNumber: true })} />
      {errors.age?.message && 

{errors.age?.message}

}
      <input type="submit" />
    </form>
  );
};

Superstruct

A simple and composable way to validate data in JavaScript (or TypeScript).

npm

```typescript jsx import { useForm } from 'react-hook-form'; import { superstructResolver } from '@hookform/resolvers/superstruct'; import { object, string, number } from 'superstruct';

const schema = object({ name: string(), age: number(), });

const App = () => { const { register, handleSubmit } = useForm({ resolver: superstructResolver(schema), });

return (

console.log(d))}> ); };


### [Joi](https://github.com/sideway/joi)

The most powerful data validation library for JS.

[![npm](https://img.shields.io/bundlephobia/minzip/joi?style=for-the-badge)](https://bundlephobia.com/result?p=joi)

```typescript jsx
import { useForm } from 'react-hook-form';
import { joiResolver } from '@hookform/resolvers/joi';
import Joi from 'joi';

const schema = Joi.object({
  name: Joi.string().required(),
  age: Joi.number().required(),
});

const App = () => {
  const { register, handleSubmit } = useForm({
    resolver: joiResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      <input type="number" {...register('age')} />
      <input type="submit" />
    </form>
  );
};

Vest

Vest 🦺 Declarative Validation Testing.

npm

```typescript jsx import { useForm } from 'react-hook-form'; import { vestResolver } from '@hookform/resolvers/vest'; import { create, test, enforce } from 'vest';

const validationSuite = create((data = {}) => { test('username', 'Username is required', () => { enforce(data.username).isNotEmpty(); });

test('password', 'Password is required', () => { enforce(data.password).isNotEmpty(); }); });

const App = () => { const { register, handleSubmit, errors } = useForm({ resolver: vestResolver(validationSuite), });

return (

console.log(data))}> ); };


### [Class Validator](https://github.com/typestack/class-validator)

Decorator-based property validation for classes.

[![npm](https://img.shields.io/bundlephobia/minzip/class-validator?style=for-the-badge)](https://bundlephobia.com/result?p=class-validator)

> ⚠️ Remember to add these options to your `tsconfig.json`!

"strictPropertyInitialization": false, "experimentalDecorators": true


```tsx
import { useForm } from 'react-hook-form';
import { classValidatorResolver } from '@hookform/resolvers/class-validator';
import { Length, Min, IsEmail } from 'class-validator';

class User {
  @Length(2, 30)
  username: string;

  @IsEmail()
  email: string;
}

const resolver = classValidatorResolver(User);

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<User>({ resolver });

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input type="text" {...register('username')} />
      {errors.username && <span>{errors.username.message}</span>}
      <input type="text" {...register('email')} />
      {errors.email && <span>{errors.email.message}</span>}
      <input type="submit" value="Submit" />
    </form>
  );
};

io-ts

Validate your data with powerful decoders.

npm

```typescript jsx import React from 'react'; import { useForm } from 'react-hook-form'; import { ioTsResolver } from '@hookform/resolvers/io-ts'; import t from 'io-ts'; // you don't have to use io-ts-types, but it's very useful import tt from 'io-ts-types';

const schema = t.type({ username: t.string, age: tt.NumberFromString, });

const App = () => { const { register, handleSubmit } = useForm({ resolver: ioTsResolver(schema), });

return (

console.log(d))}> ); };

export default App;


### [Nope](https://github.com/bvego/nope-validator)

A small, simple, and fast JS validator

[![npm](https://img.shields.io/bundlephobia/minzip/nope-validator?style=for-the-badge)](https://bundlephobia.com/result?p=nope-validator)

```typescript jsx
import { useForm } from 'react-hook-form';
import { nopeResolver } from '@hookform/resolvers/nope';
import Nope from 'nope-validator';

const schema = Nope.object().shape({
  name: Nope.string().required(),
  age: Nope.number().required(),
});

const App = () => {
  const { register, handleSubmit } = useForm({
    resolver: nopeResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      <input type="number" {...register('age')} />
      <input type="submit" />
    </form>
  );
};

computed-types

TypeScript-first schema validation with static type inference

npm

import { useForm } from 'react-hook-form';
import { computedTypesResolver } from '@hookform/resolvers/computed-types';
import Schema, { number, string } from 'computed-types';

const schema = Schema({
  username: string.min(1).error('username field is required'),
  age: number,
});

const App = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    resolver: computedTypesResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      {errors.name?.message && 

{errors.name?.message}

}
      <input type="number" {...register('age', { valueAsNumber: true })} />
      {errors.age?.message && 

{errors.age?.message}

}
      <input type="submit" />
    </form>
  );
};

typanion

Static and runtime type assertion library with no dependencies

npm

```tsx import { useForm } from 'react-hook-form'; import { typanion

Extension points exported contracts — how you extend this code

FormData (Interface)
(no doc)
joi/src/__tests__/Form-native-validation.tsx
Props (Interface)
(no doc)
typeschema/src/__tests__/Form-native-validation.tsx
FormData (Interface)
(no doc)
io-ts/src/__tests__/Form.tsx
Props (Interface)
(no doc)
yup/src/__tests__/Form-native-validation.tsx
Props (Interface)
(no doc)
ajv/src/__tests__/Form-native-validation.tsx
Props (Interface)
(no doc)
fluentvalidation-ts/src/__tests__/Form-native-validation.tsx
Props (Interface)
(no doc)
superstruct/src/__tests__/Form-native-validation.tsx
Props (Interface)
(no doc)
computed-types/src/__tests__/Form-native-validation.tsx

Core symbols most depended-on inside this repo

zodResolver
called by 40
zod/src/zod.ts
ajvResolver
called by 30
ajv/src/ajv.ts
toNestErrors
called by 29
src/toNestErrors.ts
validateFieldsNatively
called by 23
src/validateFieldsNatively.ts
yupResolver
called by 19
yup/src/yup.ts
valibotResolver
called by 16
valibot/src/valibot.ts
typeboxResolver
called by 16
typebox/src/typebox.ts
typeschemaResolver
called by 12
typeschema/src/typeschema.ts

Shape

Function 112
Interface 49
Class 18
Method 4

Languages

TypeScript100%

Modules by API surface

zod/src/zod.ts8 symbols
fluentvalidation-ts/src/__tests__/__fixtures__/data.ts7 symbols
io-ts/src/errorsToRecord.ts6 symbols
ajv/src/__tests__/__fixtures__/data-errors.ts6 symbols
fluentvalidation-ts/src/__tests__/Form.tsx5 symbols
fluentvalidation-ts/src/__tests__/Form-native-validation.tsx5 symbols
src/toNestErrors.ts4 symbols
fluentvalidation-ts/src/fluentvalidation-ts.ts4 symbols
class-validator/src/__tests__/__fixtures__/data.ts4 symbols
class-validator/src/__tests__/Form.tsx4 symbols
class-validator/src/__tests__/Form-native-validation.tsx4 symbols
vest/src/__tests__/Form.tsx3 symbols

For agents

$ claude mcp add resolvers \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact