An open API service indexing awesome lists of open source software.

https://github.com/react-hook-form/resolvers

📋 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
https://github.com/react-hook-form/resolvers

ajv class-validator computed-types form form-validation hacktoberfest hooks io-ts joi jsonschema resolvers schema-validation superstruct typebox typescript validation yup zod

Last synced: about 1 month ago
JSON representation

📋 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

Awesome Lists containing this project

README

        




React Hook Form Logo - React hook custom hook for form validation


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

[![npm downloads](https://img.shields.io/npm/dm/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)
[![npm](https://img.shields.io/npm/dt/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)
[![npm](https://img.shields.io/bundlephobia/minzip/@hookform/resolvers?style=for-the-badge)](https://bundlephobia.com/result?p=@hookform/resolvers)

## 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](https://react-hook-form.com/docs/useform#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` |

## TypeScript

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

```tsx
useForm()
```

Example:

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

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

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

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

## Links

- [React-hook-form validation resolver documentation ](https://react-hook-form.com/docs/useform#resolver)

### Supported resolvers

- [Install](#install)
- [Links](#links)
- [Supported resolvers](#supported-resolvers)
- [API](#api)
- [Quickstart](#quickstart)
- [Yup](#yup)
- [Zod](#zod)
- [Superstruct](#superstruct)
- [Joi](#joi)
- [Vest](#vest)
- [Class Validator](#class-validator)
- [io-ts](#io-ts)
- [Nope](#nope)
- [computed-types](#computed-types)
- [typanion](#typanion)
- [Ajv](#ajv)
- [TypeBox](#typebox)
- [With `ValueCheck`](#with-valuecheck)
- [With `TypeCompiler`](#with-typecompiler)
- [ArkType](#arktype)
- [Valibot](#valibot)
- [TypeSchema](#typeschema)
- [effect-ts](#effect-ts)
- [VineJS](#vinejs)
- [fluentvalidation-ts](#fluentvalidation-ts)
- [standard-schema](#standard-schema)
- [Backers](#backers)
- [Sponsors](#sponsors)
- [Contributors](#contributors)

## 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](https://github.com/jquense/yup)

Dead simple Object schema validation.

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

```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 (
console.log(d))}>




);
};
```

### [Zod](https://github.com/vriad/zod)

TypeScript-first schema validation with static type inference

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

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

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

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 (
console.log(d))}>

{errors.name?.message &&

{errors.name?.message}

}

{errors.age?.message &&

{errors.age?.message}

}


);
};
```

### [Superstruct](https://github.com/ianstormtaylor/superstruct)

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

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

```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 (
console.log(d))}>




);
};
```

### [Vest](https://github.com/ealush/vest)

Vest 🦺 Declarative Validation Testing.

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

```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({ resolver });

return (
console.log(data))}>

{errors.username && {errors.username.message}}

{errors.email && {errors.email.message}}


);
};
```

### [io-ts](https://github.com/gcanti/io-ts)

Validate your data with powerful decoders.

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

```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 (
console.log(d))}>




);
};
```

### [computed-types](https://github.com/neuledge/computed-types)

TypeScript-first schema validation with static type inference

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

```tsx
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 (
console.log(d))}>

{errors.name?.message &&

{errors.name?.message}

}

{errors.age?.message &&

{errors.age?.message}

}


);
};
```

### [typanion](https://github.com/arcanis/typanion)

Static and runtime type assertion library with no dependencies

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

```tsx
import { useForm } from 'react-hook-form';
import { typanionResolver } from '@hookform/resolvers/typanion';
import * as t from 'typanion';

const isUser = t.isObject({
username: t.applyCascade(t.isString(), [t.hasMinLength(1)]),
age: t.applyCascade(t.isNumber(), [
t.isInteger(),
t.isInInclusiveRange(1, 100),
]),
});

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

return (
console.log(d))}>

{errors.name?.message &&

{errors.name?.message}

}

{errors.age?.message &&

{errors.age?.message}

}


);
};
```

### [Ajv](https://github.com/ajv-validator/ajv)

The fastest JSON validator for Node.js and browser

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

```tsx
import { useForm } from 'react-hook-form';
import { ajvResolver } from '@hookform/resolvers/ajv';

// must use `minLength: 1` to implement required field
const schema = {
type: 'object',
properties: {
username: {
type: 'string',
minLength: 1,
errorMessage: { minLength: 'username field is required' },
},
password: {
type: 'string',
minLength: 1,
errorMessage: { minLength: 'password field is required' },
},
},
required: ['username', 'password'],
additionalProperties: false,
};

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

return (
console.log(data))}>

{errors.username && {errors.username.message}}

{errors.password && {errors.password.message}}
submit

);
};
```

### [TypeBox](https://github.com/sinclairzx81/typebox)

JSON Schema Type Builder with Static Type Resolution for TypeScript

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

#### With `ValueCheck`

```typescript jsx
import { useForm } from 'react-hook-form';
import { typeboxResolver } from '@hookform/resolvers/typebox';
import { Type } from '@sinclair/typebox';

const schema = Type.Object({
username: Type.String({ minLength: 1 }),
password: Type.String({ minLength: 1 }),
});

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

return (
console.log(d))}>




);
};
```

#### With `TypeCompiler`

A high-performance JIT of `TypeBox`, [read more](https://github.com/sinclairzx81/typebox#typecompiler)

```typescript jsx
import { useForm } from 'react-hook-form';
import { typeboxResolver } from '@hookform/resolvers/typebox';
import { Type } from '@sinclair/typebox';
import { TypeCompiler } from '@sinclair/typebox/compiler';

const schema = Type.Object({
username: Type.String({ minLength: 1 }),
password: Type.String({ minLength: 1 }),
});

const typecheck = TypeCompiler.Compile(schema);

const App = () => {
const { register, handleSubmit } = useForm({
resolver: typeboxResolver(typecheck),
});

return (
console.log(d))}>




);
};
```

### [ArkType](https://github.com/arktypeio/arktype)

TypeScript's 1:1 validator, optimized from editor to runtime

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

```typescript jsx
import { useForm } from 'react-hook-form';
import { arktypeResolver } from '@hookform/resolvers/arktype';
import { type } from 'arktype';

const schema = type({
username: 'string>1',
password: 'string>1',
});

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

return (
console.log(d))}>




);
};
```

### [Valibot](https://github.com/fabian-hiller/valibot)

The modular and type safe schema library for validating structural data

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

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

const schema = v.object({
username: v.pipe(
v.string('username is required'),
v.minLength(3, 'Needs to be at least 3 characters'),
v.endsWith('cool', 'Needs to end with `cool`'),
),
password: v.string('password is required'),
});

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

return (
console.log(d))}>




);
};
```

### [TypeSchema](https://typeschema.com)

Universal adapter for schema validation, compatible with [any validation library](https://typeschema.com/#coverage)

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

```typescript jsx
import { useForm } from 'react-hook-form';
import { typeschemaResolver } from '@hookform/resolvers/typeschema';
import { z } from 'zod';

// Use your favorite validation library
const schema = z.object({
username: z.string().min(1, { message: 'Required' }),
password: z.number().min(1, { message: 'Required' }),
});

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

return (
console.log(d))}>




);
};
```

### [effect-ts](https://github.com/Effect-TS/effect)

A powerful TypeScript framework that provides a fully-fledged functional effect system with a rich standard library.

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

```typescript jsx
import React from 'react';
import { useForm } from 'react-hook-form';
import { effectTsResolver } from '@hookform/resolvers/effect-ts';
import { Schema } from 'effect';

const schema = Schema.Struct({
username: Schema.String.pipe(
Schema.nonEmptyString({ message: () => 'username required' }),
),
password: Schema.String.pipe(
Schema.nonEmptyString({ message: () => 'password required' }),
),
});

type FormData = typeof schema.Type;

interface Props {
onSubmit: (data: FormData) => void;
}

function TestComponent({ onSubmit }: Props) {
const {
register,
handleSubmit,
formState: { errors },
// provide generic if TS has issues inferring types
} = useForm({
resolver: effectTsResolver(schema),
});

return (


{errors.username && {errors.username.message}}


{errors.password && {errors.password.message}}

submit

);
}
```

### [VineJS](https://github.com/vinejs/vine)

VineJS is a form data validation library for Node.js

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

```typescript jsx
import { useForm } from 'react-hook-form';
import { vineResolver } from '@hookform/resolvers/vine';
import vine from '@vinejs/vine';

const schema = vine.compile(
vine.object({
username: vine.string().minLength(1),
password: vine.string().minLength(1),
}),
);

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

return (
console.log(d))}>

{errors.username && {errors.username.message}}

{errors.password && {errors.password.message}}
submit

);
};
```

### [fluentvalidation-ts](https://github.com/AlexJPotter/fluentvalidation-ts)

A TypeScript-first library for building strongly-typed validation rules

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

```typescript jsx
import { useForm } from 'react-hook-form';
import { fluentValidationResolver } from '@hookform/resolvers/fluentvalidation-ts';
import { Validator } from 'fluentvalidation-ts';

class FormDataValidator extends Validator {
constructor() {
super();

this.ruleFor('username')
.notEmpty()
.withMessage('username is a required field');
this.ruleFor('password')
.notEmpty()
.withMessage('password is a required field');
}
}

const App = () => {
const { register, handleSubmit } = useForm({
resolver: fluentValidationResolver(new FormDataValidator()),
});

return (
console.log(d))}>

{errors.username && {errors.username.message}}

{errors.password && {errors.password.message}}
submit

);
};
```

### [standard-schema](https://github.com/standard-schema/standard-schema)

A standard interface for TypeScript schema validation libraries

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

Example zod

```typescript jsx
import { useForm } from 'react-hook-form';
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';
import { z } from 'zod';

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: standardSchemaResolver(schema),
});

return (
console.log(d))}>

{errors.name?.message &&

{errors.name?.message}

}

{errors.age?.message &&

{errors.age?.message}

}


);
};
```

Example arkType

```typescript jsx
import { useForm } from 'react-hook-form';
import { standardSchemaResolver } from '@hookform/resolvers/standard-schema';
import { type } from 'arktype';

const schema = type({
username: 'string>1',
password: 'string>1',
});

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

return (
console.log(d))}>




);
};
```

## Backers

Thanks go to all our backers! [[Become a backer](https://opencollective.com/react-hook-form#backer)].



## Contributors

Thanks go to these wonderful people! [[Become a contributor](CONTRIBUTING.md)].