Wit Form

createFormHooks

createFormHooks returns the Wit Form hooks typed for your form values, so TypeScript checks field names and infers value types from them.

import { createFormHooks } from 'wit-form';

const hooks = createFormHooks<Values>();

Call it once per form type, outside your components, and use the returned hooks instead of the plain ones:

interface Profile {
  name: string;
  address: { city: string };
  phones: { label: string; number: string }[];
}

const { useForm, useField, useFieldArray, Field } = createFormHooks<Profile>();

function CityField() {
  const city = useField({ name: 'address.city' }); // name is checked
  city.fieldValue; // string | undefined
  // ...
}

Read the Type-safe forms guide for fields in field array rows and other details.

Returns

The same hooks and component Wit Form exports, with stricter types. At runtime they're the very same functions.

ReturnedTyped as
useFormuseForm with Values for initialValues, onSubmit, onError, validate.
useFielduseField: name must be a path of Values (or of the row, with ancestors). The value type comes from the path.
useFieldArrayuseFieldArray: name must hold an array of objects. Row functions take the row type.
useFieldWatchuseFieldWatch: checked names, typed values.
useFieldArrayColumnWatchuseFieldArrayColumnWatch: checked array and column names, typed rows.
useFormValuesuseFormValues, returning DeepPartial<Values>.
useFormContextuseFormContext, with a typed setValue(name, ...) and getValues().
useFormStateuseFormState.
Field<Field> with a checked name.

Path types

The types used by the hooks are exported too:

TypeDescription
FieldPath<T>Every field name of T, like 'name' | 'address' | 'address.city'.
ArrayPath<T>Every path of T that holds an array of objects, like 'phones'.
PathValue<T, P>The type at path P, like PathValue<Profile, 'address.city'> → string.
DeepPartial<T>T with every property optional, at every level.

On this page