# Typescript Support

> List of exported Typescript Types.

Source: https://react-hook-form.com/ts

**Important:** TypeScript 4.1 or above is required to work with React Hook Form — several exported types (recursive `Path<T>` field-name inference, template-literal field paths) rely on generics features introduced in that release, and older versions may not type-check correctly. React Hook Form itself is developed and tested against TypeScript 6.x.

Many of the types below share two generic parameters beyond the form values type (`TFieldValues`):

- **`TContext`** — the type of the second argument passed to `useForm`'s `context` option. It's forwarded, unchanged, to your `resolver` so validation logic can read values that live outside the form (e.g. a logged-in user, feature flags).
- **`TTransformedValues`** — the shape of the data your `resolver` produces after transforming it (e.g. a Zod schema with `.transform()` that turns a string into a `Date`). It defaults to `TFieldValues` and only differs when a resolver reshapes data before it reaches `handleSubmit`'s `onValid` callback.

## Resolver

A `Resolver` lets you plug in an external validation library (such as [Zod](https://github.com/colinhacks/zod), [Yup](https://github.com/jquense/yup), or [Joi](https://github.com/hapijs/joi)) in place of React Hook Form's built-in validation. It receives the current form values and must return `{ values, errors }`.

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-resolver-forked-mjsx7)

```tsx
import { useForm, Resolver } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
}

const resolver: Resolver<FormValues> = async (values) => {
  return {
    values: values.firstName ? values : {},
    errors: !values.firstName
      ? {
          firstName: {
            type: "required",
            message: "This is required.",
          },
        }
      : {},
  }
}

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormValues>({ resolver })
  const onSubmit = handleSubmit((data) => console.log(data))

  return (
    <form onSubmit={onSubmit}>
      <input {...register("firstName")} placeholder="Bill" />
      {errors?.firstName && <p>{errors.firstName.message}</p>}

      <input {...register("lastName")} placeholder="Luo" />

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

---

## SubmitHandler

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-handlesubmit-ts-v7-z9z0g)

```tsx
import { useForm, SubmitHandler } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
  email: string
}

export default function App() {
  const { register, handleSubmit } = useForm<FormValues>()
  const onSubmit: SubmitHandler<FormValues> = (data) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <input {...register("lastName")} />
      <input type="email" {...register("email")} />

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

---

## SubmitErrorHandler

```tsx
import { useForm, SubmitHandler, SubmitErrorHandler } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
  email: string
}

export default function App() {
  const { register, handleSubmit } = useForm<FormValues>()
  const onSubmit: SubmitHandler<FormValues> = (data) => console.log(data)
  const onError: SubmitErrorHandler<FormValues> = (errors) =>
    console.log(errors)

  return (
    <form onSubmit={handleSubmit(onSubmit, onError)}>
      <input {...register("firstName", { required: true })} />
      <input {...register("lastName", { minLength: 2 })} />
      <input type="email" {...register("email")} />

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

---

## FormSubmitHandler

The type for the [`Form`](https://react-hook-form.com/docs/useform/form) component's `onSubmit` prop — unlike `SubmitHandler`, the payload includes the raw `FormData` and `formDataJson` from the submission.

```tsx
export type FormSubmitHandler<TTransformedValues> = (payload: {
  data: TTransformedValues
  event?: React.BaseSyntheticEvent
  formData: FormData
  formDataJson: string
  method?: "post" | "put" | "delete"
}) => unknown | Promise<unknown>
```

---

## Control

[Open in CodeSandbox](https://codesandbox.io/s/control-2mg07)

```tsx
import { useForm, useWatch, Control } from "react-hook-form"

type FormValues = {
  firstName: string
  lastName: string
}

function IsolateReRender({ control }: { control: Control<FormValues> }) {
  const firstName = useWatch({
    control,
    name: "firstName",
    defaultValue: "default",
  })

  return <div>{firstName}</div>
}

export default function App() {
  const { register, control, handleSubmit } = useForm<FormValues>()
  const onSubmit = handleSubmit((data) => console.log(data))

  return (
    <form onSubmit={onSubmit}>
      <input {...register("firstName")} />
      <input {...register("lastName")} />
      <IsolateReRender control={control} />

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

---

## UseFormReturn

**Type**

```tsx
export type UseFormReturn<
  TFieldValues extends FieldValues = FieldValues,
  TContext = any,
  TTransformedValues = TFieldValues,
> = {
  watch: UseFormWatch<TFieldValues>
  getValues: UseFormGetValues<TFieldValues>
  getErrors: UseFormGetErrors<TFieldValues>
  getFieldState: UseFormGetFieldState<TFieldValues>
  setError: UseFormSetError<TFieldValues>
  clearErrors: UseFormClearErrors<TFieldValues>
  setValue: UseFormSetValue<TFieldValues>
  setValues: UseFormSetValues<TFieldValues>
  trigger: UseFormTrigger<TFieldValues>
  formState: FormState<TFieldValues>
  resetField: UseFormResetField<TFieldValues>
  reset: UseFormReset<TFieldValues>
  resetDefaultValues: UseFormResetDefaultValues<TFieldValues>
  handleSubmit: UseFormHandleSubmit<TFieldValues, TTransformedValues>
  unregister: UseFormUnregister<TFieldValues>
  control: Control<TFieldValues, TContext, TTransformedValues>
  register: UseFormRegister<TFieldValues>
  setFocus: UseFormSetFocus<TFieldValues>
  subscribe: UseFormSubscribe<TFieldValues>
}
```

**Code Example**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-UseFormReturn-forked-yl40u)

```tsx
import {
  DetailedHTMLProps,
  InputHTMLAttributes,
  ReactNode,
  SelectHTMLAttributes,
  forwardRef,
} from "react"
import type { FieldValues, UseFormReturn, SubmitHandler } from "react-hook-form"
import { useForm } from "react-hook-form"

type InputProps = DetailedHTMLProps<
  InputHTMLAttributes<HTMLInputElement>,
  HTMLInputElement
>

const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => (
  <input ref={ref} {...props} />
))

type Option = {
  label: ReactNode
  value: string | number | string[]
}

type SelectProps = DetailedHTMLProps<
  SelectHTMLAttributes<HTMLSelectElement>,
  HTMLSelectElement
> & { options: Option[] }

const Select = forwardRef<HTMLSelectElement, SelectProps>(
  ({ options, ...props }, ref) => (
    <select ref={ref} {...props}>
      {options.map(({ label, value }) => (
        <option key={value} value={value}>
          {label}
        </option>
      ))}
    </select>
  )
)

type FormProps<TFormValues extends FieldValues> = {
  onSubmit: SubmitHandler<TFormValues>
  children: (methods: UseFormReturn<TFormValues>) => ReactNode
}

const Form = <TFormValues extends FieldValues>({
  onSubmit,
  children,
}: FormProps<TFormValues>) => {
  const methods = useForm<TFormValues>()
  return (
    <form onSubmit={methods.handleSubmit(onSubmit)}>{children(methods)}</form>
  )
}

type FormValues = {
  firstName: string
  lastName: string
  sex: string
}

export default function App() {
  const onSubmit = (data: FormValues) => console.log(data)

  return (
    <Form<FormValues> onSubmit={onSubmit}>
      {({ register }) => (
        <>
          <Input {...register("firstName")} />
          <Input {...register("lastName")} />
          <Select
            {...register("sex")}
            options={[
              { label: "Female", value: "female" },
              { label: "Male", value: "male" },
              { label: "Other", value: "other" },
            ]}
          />
          <Input type="submit" />
        </>
      )}
    </Form>
  )
}
```

---

## UseFormProps

```tsx
export type UseFormProps<
  TFieldValues extends FieldValues = FieldValues,
  TContext = any,
  TTransformedValues = TFieldValues,
> = Partial<{
  mode: Mode
  disabled: boolean
  reValidateMode: Exclude<Mode, "onTouched" | "all">
  defaultValues: DefaultValues<TFieldValues> | AsyncDefaultValues<TFieldValues>
  values: TFieldValues
  errors: FieldErrors<TFieldValues>
  resetOptions: Parameters<UseFormReset<TFieldValues>>[1]
  resolver: Resolver<TFieldValues, TContext, TTransformedValues>
  context: TContext
  shouldFocusError: boolean
  shouldUnregister: boolean
  shouldUseNativeValidation: boolean
  progressive: boolean
  criteriaMode: CriteriaMode
  delayError: number
  formControl?: Omit<
    UseFormReturn<TFieldValues, TContext, TTransformedValues>,
    "formState"
  >
  validate: ValidateForm<TFieldValues>
}>
```

---

## ValidateForm

The type of [`useForm`](https://react-hook-form.com/docs/useform#validate)'s `validate` option — form-level validation that runs alongside (or instead of) a `resolver`.

```tsx
export type ValidateFormEventType =
  | "blur"
  | "focusout"
  | "change"
  | "submit"
  | "trigger"
  | "valid"

export type ValidateForm<TFormValues extends FieldValues> = (props: {
  formValues: TFormValues
  formState: FormState<TFormValues>
  eventType?: ValidateFormEventType
  name?: FieldPath<TFormValues> | FieldPath<TFormValues>[]
}) => FormValidateResult<TFormValues> | Promise<FormValidateResult<TFormValues>>

export type FormValidateResult<TFormValues> =
  | Partial<
      Record<
        keyof TFormValues,
        { message: string | string[] | boolean | undefined; type: string }
      >
    >
  | string
  | boolean
```

Return `true` for a valid form. Returning a `string` sets `formState.errors.form`; returning an object keyed by field name sets `formState.errors.form.<fieldName>` for each entry.

---

## UseFormRegister

The type of [`register`](https://react-hook-form.com/docs/useform/register).

```tsx
export type UseFormRegister<TFieldValues extends FieldValues> = <
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
  name: TFieldName,
  options?: RegisterOptions<TFieldValues, TFieldName>
) => UseFormRegisterReturn<TFieldName>
```

---

## UseFormRegisterReturn

The shape returned by invoking [`register`](https://react-hook-form.com/docs/useform/register). Useful for typing a custom `Input` component that spreads `{...register(name)}`.

```tsx
export type UseFormRegisterReturn<
  TFieldName extends InternalFieldName = InternalFieldName,
> = {
  onChange: ChangeHandler
  onBlur: ChangeHandler
  ref: RefCallBack
  name: TFieldName
  min?: string | number
  max?: string | number
  maxLength?: number
  minLength?: number
  pattern?: string
  required?: boolean
  disabled?: boolean
}
```

---

## UseFormUnregister

The type of [`unregister`](https://react-hook-form.com/docs/useform/unregister).

```tsx
export type UseFormUnregister<TFieldValues extends FieldValues> = (
  name?:
    | FieldPath<TFieldValues>
    | FieldPath<TFieldValues>[]
    | readonly FieldPath<TFieldValues>[],
  options?: Omit<
    KeepStateOptions,
    | "keepIsSubmitted"
    | "keepSubmitCount"
    | "keepValues"
    | "keepDefaultValues"
    | "keepErrors"
  > & { keepValue?: boolean; keepDefaultValue?: boolean; keepError?: boolean }
) => void
```

---

## UseFormWatch

The type of [`watch`](https://react-hook-form.com/docs/useform/watch). Overloaded — called with no argument, a single field name, an array of field names, or a callback for subscribing without triggering a re-render.

```tsx
export type UseFormWatch<TFieldValues extends FieldValues> = {
  (): TFieldValues
  <TFieldNames extends readonly FieldPath<TFieldValues>[]>(
    names: readonly [...TFieldNames],
    defaultValue?: DeepPartial<TFieldValues>
  ): FieldPathValues<TFieldValues, TFieldNames>
  <TFieldName extends FieldPath<TFieldValues>>(
    name: TFieldName,
    defaultValue?: FieldPathValue<TFieldValues, TFieldName>
  ): FieldPathValue<TFieldValues, TFieldName>
  (
    callback: WatchObserver<TFieldValues>,
    defaultValues?: DeepPartial<TFieldValues>
  ): Subscription
}
```

---

## UseFormSubscribe

The type of [`subscribe`](https://react-hook-form.com/docs/useform/subscribe) — subscribe to formState changes without triggering a component re-render.

```tsx
export type UseFormSubscribe<TFieldValues extends FieldValues> = <
  TFieldNames extends readonly FieldPath<TFieldValues>[],
>(payload: {
  name?: readonly [...TFieldNames] | TFieldNames[number]
  formState?: Partial<ReadFormState>
  callback: (
    data: Partial<FormState<TFieldValues>> & {
      values: TFieldValues
      name?: InternalFieldName
      type?: EventType
    }
  ) => void
  exact?: boolean
}) => () => void
```

---

## UseFormHandleSubmit

The type of the `handleSubmit` function.

```tsx
export type SubmitHandler<T, TResult = unknown> = (
  data: T,
  event?: React.BaseSyntheticEvent
) => TResult

export type UseFormHandleSubmit<
  TFieldValues extends FieldValues,
  TTransformedValues = TFieldValues,
> = <TResult>(
  onValid: SubmitHandler<TTransformedValues, TResult>,
  onInvalid?: SubmitErrorHandler<TFieldValues>
) => (e?: React.BaseSyntheticEvent) => Promise<Awaited<TResult> | undefined>
```

---

## UseFormReset

The type of the `reset` function.

```tsx
export type UseFormReset<TFieldValues extends FieldValues> = (
  values?:
    | DefaultValues<TFieldValues>
    | TFieldValues
    | ResetAction<TFieldValues>,
  keepStateOptions?: KeepStateOptions
) => void
```

---

## UseFormResetField

The type of the `resetField` function.

```tsx
export type UseFormResetField<TFieldValues extends FieldValues> = <
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
  name: TFieldName,
  options?: ResetFieldConfig<TFieldValues, TFieldName>
) => void
```

---

## UseFormResetDefaultValues

The type of the `resetDefaultValues` function.

```tsx
export type UseFormResetDefaultValues<TFieldValues extends FieldValues> = (
  values: DefaultValues<TFieldValues> | TFieldValues,
  options?: Partial<Pick<KeepStateOptions, "keepDirty" | "keepIsValid">>
) => void
```

---

## UseFormSetError

The type of the `setError` function.

```tsx
export type UseFormSetError<TFieldValues extends FieldValues> = (
  name: FieldPath<TFieldValues> | ErrorNamespacePath,
  error: ErrorOption,
  options?: {
    shouldFocus: boolean
  }
) => void
```

---

## UseFormClearErrors

The type of the `clearErrors` function.

```tsx
export type UseFormClearErrors<TFieldValues extends FieldValues> = (
  name?:
    | FieldPath<TFieldValues>
    | FieldPath<TFieldValues>[]
    | readonly FieldPath<TFieldValues>[]
    | ErrorNamespacePath
) => void
```

---

## UseFormSetValue

The type of the `setValue` function.

```tsx
export type UseFormSetValue<TFieldValues extends FieldValues> = <
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
  name: TFieldName,
  value: FieldPathValue<TFieldValues, TFieldName>,
  options?: SetValueConfig
) => void
```

---

## UseFormSetValues

The type of the `setValues` function.

```tsx
export type UseFormSetValues<TFieldValues extends FieldValues> = (
  value: Partial<TFieldValues> | ((formValues: TFieldValues) => TFieldValues),
  options?: SetValueConfig
) => void
```

---

## UseFormSetFocus

The type of the `setFocus` function.

```tsx
export type SetFocusOptions = Partial<{
  shouldSelect: boolean
}>

export type UseFormSetFocus<TFieldValues extends FieldValues> = <
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
  name: TFieldName,
  options?: SetFocusOptions
) => void
```

---

## UseFormGetValues

The type of the `getValues` function. This type is overloaded; it can be called with no arguments, a single field name, or an array of field names.

```tsx
// Only one of `dirtyFields` or `touchedFields` can be set at a time
type EitherOption<T> = {
  [K in keyof T]: {
    [P in K]: T[P]
  } & Partial<Record<Exclude<keyof T, K>, never>>
}[keyof T]

export type GetValuesConfig = EitherOption<{
  dirtyFields: boolean
  touchedFields: boolean
}>

export type UseFormGetValues<TFieldValues extends FieldValues> = {
  (name?: undefined, config?: GetValuesConfig): TFieldValues
  <TFieldName extends FieldPath<TFieldValues>>(
    name: TFieldName,
    config?: GetValuesConfig
  ): FieldPathValue<TFieldValues, TFieldName>
  <TFieldNames extends FieldPath<TFieldValues>[]>(
    names: readonly [...TFieldNames],
    config?: GetValuesConfig
  ): [...FieldPathValues<TFieldValues, TFieldNames>]
}
```

---

## UseFormGetErrors

The type of the `getErrors` function. This type is overloaded; it can be called with no arguments, a single error path, or an array of error paths.

```tsx
export type ErrorNamespacePath =
  | "root"
  | `root.${string}`
  | "form"
  | `form.${string}`

export type GetErrorsResult<
  TFieldValues extends FieldValues,
  TName extends FieldPath<TFieldValues> | ErrorNamespacePath,
> = TName extends "root"
  ? (Record<string, GlobalError> & GlobalError) | undefined
  : TName extends ErrorNamespacePath
    ? GlobalError | undefined
    : TName extends FieldPath<TFieldValues>
      ? FieldPathError<TFieldValues, TName> | undefined
      : never

export type UseFormGetErrors<TFieldValues extends FieldValues> = {
  (name?: undefined): FieldErrors<TFieldValues>
  <TName extends FieldPath<TFieldValues> | ErrorNamespacePath>(
    name: TName
  ): GetErrorsResult<TFieldValues, TName>
  <TNames extends (FieldPath<TFieldValues> | ErrorNamespacePath)[]>(
    names: readonly [...TNames]
  ): {
    [K in keyof TNames]: GetErrorsResult<TFieldValues, TNames[K]>
  }
}
```

---

## UseFormGetFieldState

The type of the `getFieldState` function.

```tsx
export type UseFormGetFieldState<TFieldValues extends FieldValues> = <
  TFieldName extends FieldPath<TFieldValues>,
>(
  name: TFieldName,
  formState?: FormState<TFieldValues>
) => {
  invalid: boolean
  isDirty: boolean
  isTouched: boolean
  isValidating: boolean
  error?: FieldError
}
```

---

## UseFormTrigger

The type of the `trigger` function.

```tsx
export type TriggerConfig = Partial<{
  shouldFocus: boolean
  shouldTouch: boolean
}>

export type UseFormTrigger<TFieldValues extends FieldValues> = (
  name?:
    | FieldPath<TFieldValues>
    | FieldPath<TFieldValues>[]
    | readonly FieldPath<TFieldValues>[],
  options?: TriggerConfig
) => Promise<boolean>
```

---

## UseWatchProps

The props accepted by the `useWatch` hook.

```tsx
export type UseWatchProps<TFieldValues extends FieldValues = FieldValues> = {
  defaultValue?: unknown
  disabled?: boolean
  name?:
    | FieldPath<TFieldValues>
    | FieldPath<TFieldValues>[]
    | readonly FieldPath<TFieldValues>[]
  control?: Control<TFieldValues>
  exact?: boolean
  compute?: (formValues: TFieldValues) => TFieldValues
}
```

---

## WatchProps

The props for the `Watch` render-prop component.

```tsx
export type WatchProps<
  TFieldName extends WatchName<TFieldValues>,
  TFieldValues extends FieldValues = FieldValues,
  TContext = any,
  TTransformedValues = TFieldValues,
  TComputeValue = undefined,
> = {
  control?: Control<TFieldValues, TContext, TTransformedValues>
  name?: TFieldName
  disabled?: boolean
  exact?: boolean
  defaultValue?: WatchDefaultValue<TFieldName, TFieldValues>
  compute?: (value: WatchValue<TFieldName, TFieldValues>) => TComputeValue
  render: (
    value: WatchRenderValue<TFieldName, TFieldValues, TComputeValue>
  ) => React.ReactNode | React.ReactNode[]
}
```

---

## UseFormStateProps

The props accepted by the `useFormState` hook.

```tsx
export type UseFormStateProps<
  TFieldValues extends FieldValues,
  TTransformedValues = TFieldValues,
> = Partial<{
  control?: Control<TFieldValues, any, TTransformedValues>
  disabled?: boolean
  name?:
    | FieldPath<TFieldValues>
    | FieldPath<TFieldValues>[]
    | readonly FieldPath<TFieldValues>[]
  exact?: boolean
}>
```

---

## FormStateProps

The props for the `FormState` render-prop component.

```tsx
export type FormStateProps<
  TFieldValues extends FieldValues,
  TTransformedValues = TFieldValues,
> = UseFormStateProps<TFieldValues, TTransformedValues> & {
  render: (values: UseFormStateReturn<TFieldValues>) => React.ReactNode
}
```

---

## FormProviderProps

```tsx
export type FormProviderProps<
  TFieldValues extends FieldValues = FieldValues,
  TContext = any,
  TTransformedValues = TFieldValues,
> = {
  children: React.ReactNode | React.ReactNode[]
} & UseFormReturn<TFieldValues, TContext, TTransformedValues>
```

---

## FormProps

```tsx
export type FormProps<
  TFieldValues extends FieldValues,
  TTransformedValues = TFieldValues,
> = Omit<React.FormHTMLAttributes<HTMLFormElement>, "onError" | "onSubmit"> &
  Partial<{
    control: Control<TFieldValues, any, TTransformedValues>
    headers: Record<string, string>
    validateStatus: (status: number) => boolean
    onError: (
      payload:
        | { response: Response; error?: undefined }
        | { response?: undefined; error: unknown }
    ) => void
    onSuccess: ({ response }: { response: Response }) => void
    onSubmit: FormSubmitHandler<TTransformedValues>
    method: "post" | "put" | "delete"
    children: React.ReactNode | React.ReactNode[]
    render: (props: {
      submit: (e?: React.FormEvent) => void
    }) => React.ReactNode | React.ReactNode[]
    encType:
      | "application/x-www-form-urlencoded"
      | "multipart/form-data"
      | "text/plain"
      | "application/json"
  }>
```

---

## UseFieldArrayReturn

```tsx
export type UseFieldArrayReturn<
  TFieldValues extends FieldValues = FieldValues,
  TFieldArrayName extends
    FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>,
  TKeyName extends string = "id",
> = {
  swap: UseFieldArraySwap
  move: UseFieldArrayMove
  prepend: UseFieldArrayPrepend<TFieldValues, TFieldArrayName>
  append: UseFieldArrayAppend<TFieldValues, TFieldArrayName>
  remove: UseFieldArrayRemove
  insert: UseFieldArrayInsert<TFieldValues, TFieldArrayName>
  update: UseFieldArrayUpdate<TFieldValues, TFieldArrayName>
  replace: UseFieldArrayReplace<TFieldValues, TFieldArrayName>
  fields: (FieldArrayWithId<TFieldValues, TFieldArrayName, TKeyName> & {
    disabled?: boolean
  })[]
}
```

---

## FieldArrayMethodProps

Focus options accepted as the second argument to the `append`, `prepend`, and `insert` functions.

```tsx
export type FieldArrayMethodProps = {
  shouldFocus?: boolean
  focusIndex?: number
  focusName?: string
}
```

---

## UseFieldArrayProps

```tsx
export type UseFieldArrayProps<
  TFieldValues extends FieldValues = FieldValues,
  TFieldArrayName extends
    FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>,
  TKeyName extends string = "id",
  TTransformedValues = TFieldValues,
> = {
  name: TFieldArrayName
  keyName?: TKeyName
  control?: Control<TFieldValues, any, TTransformedValues>
  rules?: {
    validate?:
      | Validate<FieldArray<TFieldValues, TFieldArrayName>[], TFieldValues>
      | Record<
          string,
          Validate<FieldArray<TFieldValues, TFieldArrayName>[], TFieldValues>
        >
  } & Pick<
    RegisterOptions<TFieldValues>,
    "maxLength" | "minLength" | "required"
  >
  shouldUnregister?: boolean
  disabled?: boolean
}
```

---

## FieldArrayProps

```tsx
export type FieldArrayProps<
  TFieldValues extends FieldValues = FieldValues,
  TFieldArrayName extends
    FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>,
  TKeyName extends string = "id",
> = {
  render: (
    fieldArray: UseFieldArrayReturn<TFieldValues, TFieldArrayName, TKeyName>
  ) => React.ReactElement
} & UseFieldArrayProps<TFieldValues, TFieldArrayName, TKeyName>
```

---

## ControllerRenderProps

The shape of the `field` object passed to `Controller`'s `render` prop. Useful for typing a custom controlled input component.

```tsx
export type ControllerRenderProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
  onChange: (...event: any[]) => void
  onBlur: Noop
  value: FieldPathValue<TFieldValues, TName>
  disabled?: boolean
  name: TName
  ref: RefCallBack
}
```

---

## ControllerFieldState

The shape of the `fieldState` object passed to `Controller`'s `render` prop.

```tsx
export type ControllerFieldState = {
  invalid: boolean
  isTouched: boolean
  isDirty: boolean
  isValidating: boolean
  error?: FieldError
}
```

---

## UseControllerReturn

```tsx
export type UseControllerReturn<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
  field: ControllerRenderProps<TFieldValues, TName>
  formState: UseFormStateReturn<TFieldValues>
  fieldState: ControllerFieldState
}
```

---

## UseControllerProps

```tsx
export type UseControllerProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
  TTransformedValues = TFieldValues,
> = {
  name: TName
  rules?: Omit<
    RegisterOptions<TFieldValues, TName>,
    "valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
  >
  shouldUnregister?: boolean
  defaultValue?: FieldPathValue<TFieldValues, TName>
  control?: Control<TFieldValues, any, TTransformedValues>
  disabled?: boolean
  exact?: boolean
}
```

---

## ControllerProps

```tsx
export type ControllerProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
  TTransformedValues = TFieldValues,
> = {
  render: ({
    field,
    fieldState,
    formState,
  }: {
    field: ControllerRenderProps<TFieldValues, TName>
    fieldState: ControllerFieldState
    formState: UseFormStateReturn<TFieldValues>
  }) => React.ReactElement
} & UseControllerProps<TFieldValues, TName, TTransformedValues>
```

---

## FieldError

```tsx
export type FieldError = {
  type: LiteralUnion<keyof RegisterOptions, string>
  root?: FieldError
  ref?: Ref
  types?: MultipleFieldErrors
  message?: Message
}
```

---

## FieldErrors

```tsx
export type FieldErrors<T extends FieldValues = FieldValues> = Partial<
  FieldErrorsImpl<DeepRequired<T>>
> & {
  root?: Record<string, GlobalError> & GlobalError
  form?: GlobalError
}
```

---

## ErrorOption

The error object accepted by [`setError`](https://react-hook-form.com/docs/useform/seterror).

```tsx
export type ErrorOption = {
  message?: Message
  type?: LiteralUnion<keyof RegisterOptions, string>
  types?: MultipleFieldErrors
}
```

---

## Field

```tsx
export type Field = {
  _f: {
    ref: Ref
    name: InternalFieldName
    refs?: HTMLInputElement[]
    mount?: boolean
  } & RegisterOptions
}
```

---

## FieldPath

This type is useful when you define custom component's `name` prop, and it will type check against your field path.

```tsx
export type FieldPath<TFieldValues extends FieldValues> = Path<TFieldValues>
```

---

## FieldPathByValue

This type will return union with all available paths that match the passed value

```tsx
export type FieldPathByValue<TFieldValues extends FieldValues, TValue> = {
  [Key in FieldPath<TFieldValues>]: FieldPathValue<
    TFieldValues,
    Key
  > extends TValue
    ? Key
    : never
}[FieldPath<TFieldValues>]
```

---

## FieldValues

```tsx
export type FieldValues = Record<string, any>
```

---

## FieldArrayWithId

```tsx
export type FieldArrayWithId<
  TFieldValues extends FieldValues = FieldValues,
  TFieldArrayName extends
    FieldArrayPath<TFieldValues> = FieldArrayPath<TFieldValues>,
  TKeyName extends string = "id",
> = FieldArray<TFieldValues, TFieldArrayName> & Record<TKeyName, string>
```

---

## Mode

```tsx
export type ValidationMode = typeof VALIDATION_MODE

export type Mode = keyof ValidationMode
```

---

## RegisterOptions

```tsx
export type RegisterOptions<
  TFieldValues extends FieldValues = FieldValues,
  TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = Partial<{
  required: Message | ValidationRule<boolean>
  min: ValidationRule<number | string>
  max: ValidationRule<number | string>
  maxLength: ValidationRule<number>
  minLength: ValidationRule<number>
  validate:
    | Validate<FieldPathValue<TFieldValues, TFieldName>, TFieldValues>
    | Record<
        string,
        Validate<FieldPathValue<TFieldValues, TFieldName>, TFieldValues>
      >
  value: FieldPathValue<TFieldValues, TFieldName>
  setValueAs: (value: any) => any
  shouldUnregister?: boolean
  onChange?: (event: any) => void
  onBlur?: (event: any) => void
  disabled: boolean
  deps: FieldPath<TFieldValues> | FieldPath<TFieldValues>[]
}> &
  (
    | {
        pattern?: ValidationRule<RegExp>
        valueAsNumber?: false
        valueAsDate?: false
      }
    | {
        pattern?: undefined
        valueAsNumber?: false
        valueAsDate?: true
      }
    | {
        pattern?: undefined
        valueAsNumber?: true
        valueAsDate?: false
      }
  )
```

---

## FormState

The type of [`formState`](https://react-hook-form.com/docs/useform/formstate), returned by `useForm` and `useFormState`.

```tsx
export type FormState<TFieldValues extends FieldValues> = {
  isDirty: boolean
  isLoading: boolean
  isSubmitted: boolean
  isSubmitSuccessful: boolean
  isSubmitting: boolean
  isValidating: boolean
  isValid: boolean
  disabled: boolean
  submitCount: number
  defaultValues?: undefined | Readonly<DeepPartial<TFieldValues>>
  dirtyFields: Partial<Readonly<FieldNamesMarkedBoolean<TFieldValues>>>
  touchedFields: Partial<Readonly<FieldNamesMarkedBoolean<TFieldValues>>>
  validatingFields: Partial<Readonly<FieldNamesMarkedBoolean<TFieldValues>>>
  errors: FieldErrors<TFieldValues>
  isReady: boolean
}
```

---

## KeepStateOptions

Options accepted by [`reset`](https://react-hook-form.com/docs/useform/reset) and `useForm`'s [`resetOptions`](https://react-hook-form.com/docs/useform#resetOptions), controlling which parts of form state survive the reset.

```tsx
export type KeepStateOptions = Partial<{
  keepDirtyValues: boolean
  keepErrors: boolean
  keepDirty: boolean
  keepValues: boolean
  keepDefaultValues: boolean
  keepIsSubmitted: boolean
  keepIsSubmitSuccessful: boolean
  keepTouched: boolean
  keepIsValidating: boolean
  keepIsValid: boolean
  keepSubmitCount: boolean
  keepFieldsRef: boolean
}>
```

---

## FormStateProxy

```tsx
export type FormStateProxy<TFieldValues extends FieldValues = FieldValues> = {
  isDirty: boolean
  isValidating: boolean
  dirtyFields: FieldNamesMarkedBoolean<TFieldValues>
  touchedFields: FieldNamesMarkedBoolean<TFieldValues>
  validatingFields: FieldNamesMarkedBoolean<TFieldValues>
  errors: boolean
  isValid: boolean
}
```

---

## OpaqueTypes

A registry of types which the recursive type helpers (`Path`, `DeepPartial`, `FieldErrors`, ...) treat as opaque leaf values instead of recursing into their properties. It's empty by default and has no effect until you register a type into it via [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html).

```tsx
export interface OpaqueTypes {}

export type OpaqueType = OpaqueTypes[keyof OpaqueTypes]
```

Register a rich third-party value type — such as [Day.js](https://day.js.org/)'s `Dayjs`, [Decimal.js](https://mikemcl.github.io/decimal.js/)'s `Decimal`, or Luxon's `DateTime` — by augmenting `OpaqueTypes` in a `.d.ts` file (or anywhere the module is visible to the compiler):

```tsx
import type { Dayjs } from "dayjs"

declare module "react-hook-form" {
  interface OpaqueTypes {
    dayjs: Dayjs
  }
}
```

Once registered, any field typed as `Dayjs` (or a type that structurally contains one) is treated as a leaf by React Hook Form's internal type helpers, no matter how deeply nested it is in your form values.

### Advantage

Without registering a type, helpers such as `Path<T>` and `DeepPartial<T>` recurse into every property of every object in `TFieldValues`, including the internals of third-party classes such as `Dayjs` or `Decimal`. On a large or deeply nested form this recursion can be expensive enough for TypeScript to emit an "excessively deep" complexity diagnostic, or simply slow down editor type-checking.

Registering a type in `OpaqueTypes` tells those helpers to stop at that type and treat it as a single leaf value rather than an object to traverse — the same way `Date` and `FileList` are already handled internally. This keeps field-path inference and other generic type computations fast and accurate for forms that store rich objects instead of plain primitives.

---

## NestedValue (**Deprecated** at 7.33.0)

`NestedValue` is deprecated and will be removed in a future major version. For
a non-primitive value that needs to stay controlled (such as the array values
below), type the field normally in your form values and wire it up with
[`Controller`](https://react-hook-form.com/docs/usecontroller/controller) instead of wrapping the type in
`NestedValue`.

**Code Example**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-nestedvalue-lskdv)

```tsx
import { useEffect } from "react"
import { useForm, NestedValue } from "react-hook-form"
import { TextField, Select, MenuItem } from "@mui/material"
import { Autocomplete } from "@mui/material"

type Option = {
  label: string
  value: string
}

const options = [
  { label: "Chocolate", value: "chocolate" },
  { label: "Strawberry", value: "strawberry" },
  { label: "Vanilla", value: "vanilla" },
]

export default function App() {
  const {
    register,
    handleSubmit,
    watch,
    setValue,
    formState: { errors },
  } = useForm<{
    autocomplete: NestedValue<Option[]>
    select: NestedValue<number[]>
  }>({
    defaultValues: { autocomplete: [], select: [] },
  })
  const onSubmit = handleSubmit((data) => console.log(data))

  useEffect(() => {
    register("autocomplete", {
      validate: (value) => value.length || "This is required.",
    })
    register("select", {
      validate: (value) => value.length || "This is required.",
    })
  }, [register])

  return (
    <form onSubmit={onSubmit}>
      <Autocomplete
        options={options}
        getOptionLabel={(option: Option) => option.label}
        onChange={(e, options) => setValue("autocomplete", options)}
        renderInput={(params) => (
          <TextField
            {...params}
            error={Boolean(errors?.autocomplete)}
            helperText={errors?.autocomplete?.message}
          />
        )}
      />

      <Select
        value=""
        multiple
        // cast required because NestedValue<number[]> bypasses field-level type inference
        onChange={(e) => setValue("select", e.target.value as number[])}
      >
        <MenuItem value={10}>Ten</MenuItem>
        <MenuItem value={20}>Twenty</MenuItem>
      </Select>

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

**Type**

```tsx
import { useForm, NestedValue } from "react-hook-form"

type FormValues = {
  key1: string
  key2: number
  key3: NestedValue<{
    key1: string
    key2: number
  }>
  key4: NestedValue<string[]>
}

const {
  formState: { errors },
} = useForm<FormValues>()

errors?.key1?.message // no type error
errors?.key2?.message // no type error
errors?.key3?.message // no type error
errors?.key4?.message // no type error
```
