Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@hookform/resolvers

react-hook-form12.6mMIT3.10.0TypeScript support: included

React Hook Form validation resolvers: Yup, Joi, Superstruct, Zod, Vest, Class Validator, io-ts, Nope, computed-types, TypeBox, arktype, Typanion, Effect-TS and VineJS

scheme, validation, scheme-validation, hookform, react-hook-form, yup, joi, superstruct, typescript, zod, vest, class-validator, io-ts, effect-ts, nope, computed-types, typanion, ajv, TypeBox, arktype, typeschema, vine, fluentvalidation-ts

readme

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

npm downloads npm npm

Install

npm install @hookform/resolvers

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

`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](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 * as 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 (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      {errors.name?.message && <p>{errors.name?.message}</p>}
      <input type="number" {...register('age', { valueAsNumber: true })} />
      {errors.age?.message && <p>{errors.age?.message}</p>}
      <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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('name')} /> <input type="number" {...register('age', { valueAsNumber: true })} /> <input type="submit" /> </form> ); };


### [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 ( <form onSubmit={handleSubmit((data) => console.log(data))}> <input {...register('username')} /> <input type="password" {...register('password')} /> <input type="submit" /> </form> ); };


### [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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('username')} /> <input type="number" {...register('age')} /> <input type="submit" /> </form> ); };

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 && <p>{errors.name?.message}</p>}
      <input type="number" {...register('age', { valueAsNumber: true })} />
      {errors.age?.message && <p>{errors.age?.message}</p>}
      <input type="submit" />
    </form>
  );
};

typanion

Static and runtime type assertion library with no dependencies

npm

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 (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('name')} />
      {errors.name?.message && <p>{errors.name?.message}</p>}
      <input type="number" {...register('age')} />
      {errors.age?.message && <p>{errors.age?.message}</p>}
      <input type="submit" />
    </form>
  );
};

Ajv

The fastest JSON validator for Node.js and browser

npm

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 (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register('username')} />
      {errors.username && <span>{errors.username.message}</span>}
      <input {...register('password')} />
      {errors.password && <span>{errors.password.message}</span>}
      <button type="submit">submit</button>
    </form>
  );
};

TypeBox

JSON Schema Type Builder with Static Type Resolution for TypeScript

npm

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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('username')} /> <input type="password" {...register('password')} /> <input type="submit" /> </form> ); };


#### 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 (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('username')} />
      <input type="password" {...register('password')} />
      <input type="submit" />
    </form>
  );
};

ArkType

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

npm

`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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('username')} /> <input type="password" {...register('password')} /> <input type="submit" /> </form> ); };


### [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 (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('username')} />
      <input type="password" {...register('password')} />
      <input type="submit" />
    </form>
  );
};

TypeSchema

Universal adapter for schema validation, compatible with any validation library

npm

`typescript jsx import { useForm } from 'react-hook-form'; import { typeschemaResolver } from '@hookform/resolvers/typeschema'; import * as 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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('username')} /> <input type="password" {...register('password')} /> <input type="submit" /> </form> ); };


### [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.nonEmpty({ message: () => 'username required' }),
  ),
  password: Schema.String.pipe(
    Schema.nonEmpty({ 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<FormData>({
    resolver: effectTsResolver(schema),
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('username')} />
      {errors.username && <span role="alert">{errors.username.message}</span>}

      <input {...register('password')} />
      {errors.password && <span role="alert">{errors.password.message}</span>}

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

VineJS

VineJS is a form data validation library for Node.js

npm

`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 ( <form onSubmit={handleSubmit((d) => console.log(d))}> <input {...register('username')} /> {errors.username && {errors.username.message}} <input {...register('password')} /> {errors.password && {errors.password.message}} <button type="submit">submit</button> </form> ); };



### [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<FormData> {
  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 (
    <form onSubmit={handleSubmit((d) => console.log(d))}>
      <input {...register('username')} />
      {errors.username && <span role="alert">{errors.username.message}</span>}
      <input {...register('password')} />
      {errors.password && <span role="alert">{errors.password.message}</span>}
      <button type="submit">submit</button>
    </form>
  );
};

Backers

Thanks go to all our backers! [Become a backer].

Contributors

Thanks go to these wonderful people! [Become a contributor].