{"id":13455384,"url":"https://github.com/react-hook-form/resolvers","last_synced_at":"2025-05-16T01:03:04.019Z","repository":{"id":38108213,"uuid":"257580194","full_name":"react-hook-form/resolvers","owner":"react-hook-form","description":"📋 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","archived":false,"fork":false,"pushed_at":"2025-04-02T05:50:25.000Z","size":2287,"stargazers_count":1982,"open_issues_count":30,"forks_count":185,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-05-16T01:01:48.677Z","etag":null,"topics":["ajv","class-validator","computed-types","form","form-validation","hacktoberfest","hooks","io-ts","joi","jsonschema","resolvers","schema-validation","superstruct","typebox","typescript","validation","yup","zod"],"latest_commit_sha":null,"homepage":"https://react-hook-form.com/docs/useform#resolver","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/react-hook-form.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["bluebill1049","jorisre"],"patreon":"bluebill1049","open_collective":"react-hook-form"}},"created_at":"2020-04-21T11:56:22.000Z","updated_at":"2025-05-15T17:02:31.000Z","dependencies_parsed_at":"2023-12-14T21:04:59.331Z","dependency_job_id":"6b130379-a849-4506-96f9-bafa150b4642","html_url":"https://github.com/react-hook-form/resolvers","commit_stats":{"total_commits":331,"total_committers":53,"mean_commits":6.245283018867925,"dds":0.6918429003021148,"last_synced_commit":"5fc1e63c24a516dd83c6eb4833f55bba4c81d2a4"},"previous_names":["react-hook-form/react-hook-form-resolvers"],"tags_count":107,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-hook-form%2Fresolvers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-hook-form%2Fresolvers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-hook-form%2Fresolvers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-hook-form%2Fresolvers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react-hook-form","download_url":"https://codeload.github.com/react-hook-form/resolvers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254448579,"owners_count":22072764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ajv","class-validator","computed-types","form","form-validation","hacktoberfest","hooks","io-ts","joi","jsonschema","resolvers","schema-validation","superstruct","typebox","typescript","validation","yup","zod"],"created_at":"2024-07-31T08:01:04.705Z","updated_at":"2025-05-16T01:03:03.830Z","avatar_url":"https://github.com/react-hook-form.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n    \u003cp align=\"center\"\u003e\n        \u003ca href=\"https://react-hook-form.com\" title=\"React Hook Form - Simple React forms validation\"\u003e\n            \u003cimg 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\" /\u003e\n        \u003c/a\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003ePerformant, flexible and extensible forms with easy to use validation.\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![npm downloads](https://img.shields.io/npm/dm/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)\n[![npm](https://img.shields.io/npm/dt/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)\n[![npm](https://img.shields.io/bundlephobia/minzip/@hookform/resolvers?style=for-the-badge)](https://bundlephobia.com/result?p=@hookform/resolvers)\n\n\u003c/div\u003e\n\n## React Hook Form Resolvers\n\nThis 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.\n\n## Install\n\nInstall your preferred validation library alongside `@hookform/resolvers`.\n    \n    npm install @hookform/resolvers # npm\n    yarn add @hookform/resolvers # yarn\n    pnpm install @hookform/resolvers # pnpm\n    bun install @hookform/resolvers # bun\n\n\u003cdetails\u003e\n  \u003csummary\u003eResolver Comparison\u003c/summary\u003e\n \n| resolver  | Infer values \u003cbr /\u003e from schema | [criteriaMode](https://react-hook-form.com/docs/useform#criteriaMode) |\n|---|---|---|\n| AJV  | ❌  | `firstError | all` |\n| Arktype |  ✅ | `firstError` |\n| class-validator  | ✅  | `firstError | all` |\n| computed-types  | ✅  | `firstError` |\n| Effect  | ✅  | `firstError | all` |\n| fluentvalidation-ts  | ❌  | `firstError` |\n| io-ts  | ✅  | `firstError` |\n| joi |  ❌ | `firstError | all` |\n| Nope  | ❌  | `firstError` |\n| Standard Schema  | ✅  | `firstError | all` |\n| Superstruct  | ✅  | `firstError` |\n| typanion  | ✅  | `firstError` |\n| typebox  | ✅  | `firstError | all` |\n| typeschema  | ❌  | `firstError | all` |\n| valibot  | ✅  | `firstError | all` |\n| vest  | ❌  | `firstError | all` |\n| vine  | ✅  | `firstError | all` |\n| yup  | ✅  | `firstError | all` |\n| zod  | ✅ | `firstError | all` |\n\u003c/details\u003e\n\n## TypeScript\n\nMost of the resolvers can infer the output type from the schema. See comparison table for more details.\n\n```tsx\nuseForm\u003cInput, Context, Output\u003e()\n```\n\nExample:\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  id: z.number(),\n});\n\n// Automatically infers the output type from the schema\nuseForm({\n  resolver: zodResolver(schema),\n});\n\n// Force the output type\nuseForm\u003cz.input\u003ctypeof schema\u003e, any, z.output\u003ctypeof schema\u003e\u003e({\n  resolver: zodResolver(schema),\n});\n```\n\n## Links\n\n- [React-hook-form validation resolver documentation ](https://react-hook-form.com/docs/useform#resolver)\n\n### Supported resolvers\n\n- [Install](#install)\n- [Links](#links)\n  - [Supported resolvers](#supported-resolvers)\n- [API](#api)\n- [Quickstart](#quickstart)\n  - [Yup](#yup)\n  - [Zod](#zod)\n  - [Superstruct](#superstruct)\n  - [Joi](#joi)\n  - [Vest](#vest)\n  - [Class Validator](#class-validator)\n  - [io-ts](#io-ts)\n  - [Nope](#nope)\n  - [computed-types](#computed-types)\n  - [typanion](#typanion)\n  - [Ajv](#ajv)\n  - [TypeBox](#typebox)\n    - [With `ValueCheck`](#with-valuecheck)\n    - [With `TypeCompiler`](#with-typecompiler)\n  - [ArkType](#arktype)\n  - [Valibot](#valibot)\n  - [TypeSchema](#typeschema)\n  - [effect-ts](#effect-ts)\n  - [VineJS](#vinejs)\n  - [fluentvalidation-ts](#fluentvalidation-ts)\n  - [standard-schema](#standard-schema)\n- [Backers](#backers)\n  - [Sponsors](#sponsors)\n- [Contributors](#contributors)\n\n## API\n\n```\ntype Options = {\n  mode: 'async' | 'sync',\n  raw?: boolean\n}\n\nresolver(schema: object, schemaOptions?: object, resolverOptions: Options)\n```\n\n|                 | type     | Required | Description                                   |\n| --------------- | -------- | -------- | --------------------------------------------- |\n| schema          | `object` | ✓        | validation schema                             |\n| schemaOptions   | `object` |          | validation library schema options             |\n| resolverOptions | `object` |          | resolver options, `async` is the default mode |\n\n## Quickstart\n\n### [Yup](https://github.com/jquense/yup)\n\nDead simple Object schema validation.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/yup?style=for-the-badge)](https://bundlephobia.com/result?p=yup)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { yupResolver } from '@hookform/resolvers/yup';\nimport * as yup from 'yup';\n\nconst schema = yup\n  .object()\n  .shape({\n    name: yup.string().required(),\n    age: yup.number().required(),\n  })\n  .required();\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: yupResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      \u003cinput type=\"number\" {...register('age')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Zod](https://github.com/vriad/zod)\n\nTypeScript-first schema validation with static type inference\n\n[![npm](https://img.shields.io/bundlephobia/minzip/zod?style=for-the-badge)](https://bundlephobia.com/result?p=zod)\n\n\u003e ⚠️ Example below uses the `valueAsNumber`, which requires `react-hook-form` v6.12.0 (released Nov 28, 2020) or later.\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  name: z.string().min(1, { message: 'Required' }),\n  age: z.number().min(10),\n});\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm({\n    resolver: zodResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      {errors.name?.message \u0026\u0026 \u003cp\u003e{errors.name?.message}\u003c/p\u003e}\n      \u003cinput type=\"number\" {...register('age', { valueAsNumber: true })} /\u003e\n      {errors.age?.message \u0026\u0026 \u003cp\u003e{errors.age?.message}\u003c/p\u003e}\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Superstruct](https://github.com/ianstormtaylor/superstruct)\n\nA simple and composable way to validate data in JavaScript (or TypeScript).\n\n[![npm](https://img.shields.io/bundlephobia/minzip/superstruct?style=for-the-badge)](https://bundlephobia.com/result?p=superstruct)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { superstructResolver } from '@hookform/resolvers/superstruct';\nimport { object, string, number } from 'superstruct';\n\nconst schema = object({\n  name: string(),\n  age: number(),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: superstructResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      \u003cinput type=\"number\" {...register('age', { valueAsNumber: true })} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Joi](https://github.com/sideway/joi)\n\nThe most powerful data validation library for JS.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/joi?style=for-the-badge)](https://bundlephobia.com/result?p=joi)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { joiResolver } from '@hookform/resolvers/joi';\nimport Joi from 'joi';\n\nconst schema = Joi.object({\n  name: Joi.string().required(),\n  age: Joi.number().required(),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: joiResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      \u003cinput type=\"number\" {...register('age')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Vest](https://github.com/ealush/vest)\n\nVest 🦺 Declarative Validation Testing.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/vest?style=for-the-badge)](https://bundlephobia.com/result?p=vest)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { vestResolver } from '@hookform/resolvers/vest';\nimport { create, test, enforce } from 'vest';\n\nconst validationSuite = create((data = {}) =\u003e {\n  test('username', 'Username is required', () =\u003e {\n    enforce(data.username).isNotEmpty();\n  });\n\n  test('password', 'Password is required', () =\u003e {\n    enforce(data.password).isNotEmpty();\n  });\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit, errors } = useForm({\n    resolver: vestResolver(validationSuite),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((data) =\u003e console.log(data))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Class Validator](https://github.com/typestack/class-validator)\n\nDecorator-based property validation for classes.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/class-validator?style=for-the-badge)](https://bundlephobia.com/result?p=class-validator)\n\n\u003e ⚠️ Remember to add these options to your `tsconfig.json`!\n\n```\n\"strictPropertyInitialization\": false,\n\"experimentalDecorators\": true\n```\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { classValidatorResolver } from '@hookform/resolvers/class-validator';\nimport { Length, Min, IsEmail } from 'class-validator';\n\nclass User {\n  @Length(2, 30)\n  username: string;\n\n  @IsEmail()\n  email: string;\n}\n\nconst resolver = classValidatorResolver(User);\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm\u003cUser\u003e({ resolver });\n\n  return (\n    \u003cform onSubmit={handleSubmit((data) =\u003e console.log(data))}\u003e\n      \u003cinput type=\"text\" {...register('username')} /\u003e\n      {errors.username \u0026\u0026 \u003cspan\u003e{errors.username.message}\u003c/span\u003e}\n      \u003cinput type=\"text\" {...register('email')} /\u003e\n      {errors.email \u0026\u0026 \u003cspan\u003e{errors.email.message}\u003c/span\u003e}\n      \u003cinput type=\"submit\" value=\"Submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [io-ts](https://github.com/gcanti/io-ts)\n\nValidate your data with powerful decoders.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/io-ts?style=for-the-badge)](https://bundlephobia.com/result?p=io-ts)\n\n```typescript jsx\nimport React from 'react';\nimport { useForm } from 'react-hook-form';\nimport { ioTsResolver } from '@hookform/resolvers/io-ts';\nimport t from 'io-ts';\n// you don't have to use io-ts-types, but it's very useful\nimport tt from 'io-ts-types';\n\nconst schema = t.type({\n  username: t.string,\n  age: tt.NumberFromString,\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: ioTsResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"number\" {...register('age')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n\nexport default App;\n```\n\n### [Nope](https://github.com/bvego/nope-validator)\n\nA small, simple, and fast JS validator\n\n[![npm](https://img.shields.io/bundlephobia/minzip/nope-validator?style=for-the-badge)](https://bundlephobia.com/result?p=nope-validator)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { nopeResolver } from '@hookform/resolvers/nope';\nimport Nope from 'nope-validator';\n\nconst schema = Nope.object().shape({\n  name: Nope.string().required(),\n  age: Nope.number().required(),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: nopeResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      \u003cinput type=\"number\" {...register('age')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [computed-types](https://github.com/neuledge/computed-types)\n\nTypeScript-first schema validation with static type inference\n\n[![npm](https://img.shields.io/bundlephobia/minzip/computed-types?style=for-the-badge)](https://bundlephobia.com/result?p=computed-types)\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { computedTypesResolver } from '@hookform/resolvers/computed-types';\nimport Schema, { number, string } from 'computed-types';\n\nconst schema = Schema({\n  username: string.min(1).error('username field is required'),\n  age: number,\n});\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm({\n    resolver: computedTypesResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      {errors.name?.message \u0026\u0026 \u003cp\u003e{errors.name?.message}\u003c/p\u003e}\n      \u003cinput type=\"number\" {...register('age', { valueAsNumber: true })} /\u003e\n      {errors.age?.message \u0026\u0026 \u003cp\u003e{errors.age?.message}\u003c/p\u003e}\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [typanion](https://github.com/arcanis/typanion)\n\nStatic and runtime type assertion library with no dependencies\n\n[![npm](https://img.shields.io/bundlephobia/minzip/typanion?style=for-the-badge)](https://bundlephobia.com/result?p=typanion)\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { typanionResolver } from '@hookform/resolvers/typanion';\nimport * as t from 'typanion';\n\nconst isUser = t.isObject({\n  username: t.applyCascade(t.isString(), [t.hasMinLength(1)]),\n  age: t.applyCascade(t.isNumber(), [\n    t.isInteger(),\n    t.isInInclusiveRange(1, 100),\n  ]),\n});\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm({\n    resolver: typanionResolver(isUser),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      {errors.name?.message \u0026\u0026 \u003cp\u003e{errors.name?.message}\u003c/p\u003e}\n      \u003cinput type=\"number\" {...register('age')} /\u003e\n      {errors.age?.message \u0026\u0026 \u003cp\u003e{errors.age?.message}\u003c/p\u003e}\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Ajv](https://github.com/ajv-validator/ajv)\n\nThe fastest JSON validator for Node.js and browser\n\n[![npm](https://img.shields.io/bundlephobia/minzip/ajv?style=for-the-badge)](https://bundlephobia.com/result?p=ajv)\n\n```tsx\nimport { useForm } from 'react-hook-form';\nimport { ajvResolver } from '@hookform/resolvers/ajv';\n\n// must use `minLength: 1` to implement required field\nconst schema = {\n  type: 'object',\n  properties: {\n    username: {\n      type: 'string',\n      minLength: 1,\n      errorMessage: { minLength: 'username field is required' },\n    },\n    password: {\n      type: 'string',\n      minLength: 1,\n      errorMessage: { minLength: 'password field is required' },\n    },\n  },\n  required: ['username', 'password'],\n  additionalProperties: false,\n};\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm({\n    resolver: ajvResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((data) =\u003e console.log(data))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      {errors.username \u0026\u0026 \u003cspan\u003e{errors.username.message}\u003c/span\u003e}\n      \u003cinput {...register('password')} /\u003e\n      {errors.password \u0026\u0026 \u003cspan\u003e{errors.password.message}\u003c/span\u003e}\n      \u003cbutton type=\"submit\"\u003esubmit\u003c/button\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [TypeBox](https://github.com/sinclairzx81/typebox)\n\nJSON Schema Type Builder with Static Type Resolution for TypeScript\n\n[![npm](https://img.shields.io/bundlephobia/minzip/@sinclair/typebox?style=for-the-badge)](https://bundlephobia.com/result?p=@sinclair/typebox)\n\n#### With `ValueCheck`\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { typeboxResolver } from '@hookform/resolvers/typebox';\nimport { Type } from '@sinclair/typebox';\n\nconst schema = Type.Object({\n  username: Type.String({ minLength: 1 }),\n  password: Type.String({ minLength: 1 }),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: typeboxResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n#### With `TypeCompiler`\n\nA high-performance JIT of `TypeBox`, [read more](https://github.com/sinclairzx81/typebox#typecompiler)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { typeboxResolver } from '@hookform/resolvers/typebox';\nimport { Type } from '@sinclair/typebox';\nimport { TypeCompiler } from '@sinclair/typebox/compiler';\n\nconst schema = Type.Object({\n  username: Type.String({ minLength: 1 }),\n  password: Type.String({ minLength: 1 }),\n});\n\nconst typecheck = TypeCompiler.Compile(schema);\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: typeboxResolver(typecheck),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [ArkType](https://github.com/arktypeio/arktype)\n\nTypeScript's 1:1 validator, optimized from editor to runtime\n\n[![npm](https://img.shields.io/bundlephobia/minzip/arktype?style=for-the-badge)](https://bundlephobia.com/result?p=arktype)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { arktypeResolver } from '@hookform/resolvers/arktype';\nimport { type } from 'arktype';\n\nconst schema = type({\n  username: 'string\u003e1',\n  password: 'string\u003e1',\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: arktypeResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [Valibot](https://github.com/fabian-hiller/valibot)\n\nThe modular and type safe schema library for validating structural data\n\n[![npm](https://img.shields.io/bundlephobia/minzip/valibot?style=for-the-badge)](https://bundlephobia.com/result?p=valibot)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { valibotResolver } from '@hookform/resolvers/valibot';\nimport * as v from 'valibot';\n\nconst schema = v.object({\n  username: v.pipe(\n    v.string('username is required'),\n    v.minLength(3, 'Needs to be at least 3 characters'),\n    v.endsWith('cool', 'Needs to end with `cool`'),\n  ),\n  password: v.string('password is required'),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: valibotResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [TypeSchema](https://typeschema.com)\n\nUniversal adapter for schema validation, compatible with [any validation library](https://typeschema.com/#coverage)\n\n[![npm](https://img.shields.io/bundlephobia/minzip/@typeschema/main?style=for-the-badge)](https://bundlephobia.com/result?p=@typeschema/main)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { typeschemaResolver } from '@hookform/resolvers/typeschema';\nimport { z } from 'zod';\n\n// Use your favorite validation library\nconst schema = z.object({\n  username: z.string().min(1, { message: 'Required' }),\n  password: z.number().min(1, { message: 'Required' }),\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: typeschemaResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [effect-ts](https://github.com/Effect-TS/effect)\n\nA powerful TypeScript framework that provides a fully-fledged functional effect system with a rich standard library.\n\n[![npm](https://img.shields.io/bundlephobia/minzip/effect?style=for-the-badge)](https://bundlephobia.com/result?p=effect)\n\n```typescript jsx\nimport React from 'react';\nimport { useForm } from 'react-hook-form';\nimport { effectTsResolver } from '@hookform/resolvers/effect-ts';\nimport { Schema } from 'effect';\n\nconst schema = Schema.Struct({\n  username: Schema.String.pipe(\n    Schema.nonEmptyString({ message: () =\u003e 'username required' }),\n  ),\n  password: Schema.String.pipe(\n    Schema.nonEmptyString({ message: () =\u003e 'password required' }),\n  ),\n});\n\ntype FormData = typeof schema.Type;\n\ninterface Props {\n  onSubmit: (data: FormData) =\u003e void;\n}\n\nfunction TestComponent({ onSubmit }: Props) {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n    // provide generic if TS has issues inferring types\n  } = useForm\u003cFormData\u003e({\n    resolver: effectTsResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit(onSubmit)}\u003e\n      \u003cinput {...register('username')} /\u003e\n      {errors.username \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.username.message}\u003c/span\u003e}\n\n      \u003cinput {...register('password')} /\u003e\n      {errors.password \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.password.message}\u003c/span\u003e}\n\n      \u003cbutton type=\"submit\"\u003esubmit\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\n### [VineJS](https://github.com/vinejs/vine)\n\nVineJS is a form data validation library for Node.js\n\n[![npm](https://img.shields.io/bundlephobia/minzip/@vinejs/vine?style=for-the-badge)](https://bundlephobia.com/result?p=@vinejs/vine)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { vineResolver } from '@hookform/resolvers/vine';\nimport vine from '@vinejs/vine';\n\nconst schema = vine.compile(\n  vine.object({\n    username: vine.string().minLength(1),\n    password: vine.string().minLength(1),\n  }),\n);\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: vineResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      {errors.username \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.username.message}\u003c/span\u003e}\n      \u003cinput {...register('password')} /\u003e\n      {errors.password \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.password.message}\u003c/span\u003e}\n      \u003cbutton type=\"submit\"\u003esubmit\u003c/button\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n\n### [fluentvalidation-ts](https://github.com/AlexJPotter/fluentvalidation-ts)\n\nA TypeScript-first library for building strongly-typed validation rules\n\n[![npm](https://img.shields.io/bundlephobia/minzip/@vinejs/vine?style=for-the-badge)](https://bundlephobia.com/result?p=@vinejs/vine)\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { fluentValidationResolver } from '@hookform/resolvers/fluentvalidation-ts';\nimport { Validator } from 'fluentvalidation-ts';\n\nclass FormDataValidator extends Validator\u003cFormData\u003e {\n  constructor() {\n    super();\n\n    this.ruleFor('username')\n      .notEmpty()\n      .withMessage('username is a required field');\n    this.ruleFor('password')\n      .notEmpty()\n      .withMessage('password is a required field');\n  }\n}\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: fluentValidationResolver(new FormDataValidator()),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      {errors.username \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.username.message}\u003c/span\u003e}\n      \u003cinput {...register('password')} /\u003e\n      {errors.password \u0026\u0026 \u003cspan role=\"alert\"\u003e{errors.password.message}\u003c/span\u003e}\n      \u003cbutton type=\"submit\"\u003esubmit\u003c/button\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n### [standard-schema](https://github.com/standard-schema/standard-schema)\n\nA standard interface for TypeScript schema validation libraries\n\n[![npm](https://img.shields.io/bundlephobia/minzip/@standard-schema/spec?style=for-the-badge)](https://bundlephobia.com/result?p=@standard-schema/spec)\n\nExample zod\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  name: z.string().min(1, { message: 'Required' }),\n  age: z.number().min(10),\n});\n\nconst App = () =\u003e {\n  const {\n    register,\n    handleSubmit,\n    formState: { errors },\n  } = useForm({\n    resolver: standardSchemaResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('name')} /\u003e\n      {errors.name?.message \u0026\u0026 \u003cp\u003e{errors.name?.message}\u003c/p\u003e}\n      \u003cinput type=\"number\" {...register('age', { valueAsNumber: true })} /\u003e\n      {errors.age?.message \u0026\u0026 \u003cp\u003e{errors.age?.message}\u003c/p\u003e}\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\nExample arkType\n\n```typescript jsx\nimport { useForm } from 'react-hook-form';\nimport { standardSchemaResolver } from '@hookform/resolvers/standard-schema';\nimport { type } from 'arktype';\n\nconst schema = type({\n  username: 'string\u003e1',\n  password: 'string\u003e1',\n});\n\nconst App = () =\u003e {\n  const { register, handleSubmit } = useForm({\n    resolver: standardSchemaResolver(schema),\n  });\n\n  return (\n    \u003cform onSubmit={handleSubmit((d) =\u003e console.log(d))}\u003e\n      \u003cinput {...register('username')} /\u003e\n      \u003cinput type=\"password\" {...register('password')} /\u003e\n      \u003cinput type=\"submit\" /\u003e\n    \u003c/form\u003e\n  );\n};\n```\n\n## Backers\n\nThanks go to all our backers! [[Become a backer](https://opencollective.com/react-hook-form#backer)].\n\n\u003ca href=\"https://opencollective.com/react-hook-form#backers\"\u003e\n    \u003cimg src=\"https://opencollective.com/react-hook-form/backers.svg?width=950\" /\u003e\n\u003c/a\u003e\n\n## Contributors\n\nThanks go to these wonderful people! [[Become a contributor](CONTRIBUTING.md)].\n\n\u003ca href=\"https://github.com/react-hook-form/react-hook-form/graphs/contributors\"\u003e\n    \u003cimg src=\"https://opencollective.com/react-hook-form/contributors.svg?width=950\" /\u003e\n\u003c/a\u003e\n","funding_links":["https://github.com/sponsors/bluebill1049","https://github.com/sponsors/jorisre","https://patreon.com/bluebill1049","https://opencollective.com/react-hook-form"],"categories":["TypeScript","typescript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-hook-form%2Fresolvers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact-hook-form%2Fresolvers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-hook-form%2Fresolvers/lists"}