Skip to content

Instantly share code, notes, and snippets.

@kendallroth
Last active June 15, 2023 20:32
Show Gist options
  • Save kendallroth/fa91338c09e79555a3b23f59297306c1 to your computer and use it in GitHub Desktop.
Save kendallroth/fa91338c09e79555a3b23f59297306c1 to your computer and use it in GitHub Desktop.
Strongly type React Hook Form field names

Typing RHF Fields

While react-hook-form supports strong typing everywhere, including support for types inferred from a Yup schema (Yup.InferType<Schema>), passing field names to controls is still untyped. However, this can be resolved with RHF's FieldPath type and a helper function.

Options

// Option 1: Declared per form, less boilerplate per control
export const getOrganizationFormField = (name: FieldPath<OrganizationForm>) => name;
getOrganizationFormField("billingAddress.address1");

// Option 2: Declared globally, more boilerplate per control
export const getFormField = <T extends FieldValues>(name: FieldPath<T>) => name;
getFormField<OrganizationForm>("billingAddress.address1");

// Option 3: Declared globally but extended per form, hybrid
export const getFormField = <T extends FieldValues>(name: FieldPath<T>) => name;
export const getOrganizationFormField = getFormField<OrganizationForm>;
getOrgFormField("billingAddress.address1");

Hybrid Approach

// utils.ts
/**
 * Support strongly typing RHF form field names (when using in UI, etc)
 *
 * @param   name - Field names (strongly typed)
 * @returns Typed field name
 *
 * @example
 * const getTypedFormField = <T extends FieldValues>(name: FieldPath<T>) => name;
 *
 * type FormSchema = Yup.InferType<{ ... }>;
 * const getFormField = getTypedFormField<FormSchema>;
 *
 * return <Input name={getFormField("strongly.typed")} />;
 */
export const getTypedFormField = <T extends FieldValues>(name: FieldPath<T>) => name;
// MemberForm.tsx
type OrganizationForm = Yup.InferType<{ ... }>;

// "Alias" the global function with the inferred type to reduce boilerplate
const getFormField = getTypedFormField<OrganizationForm>;

return <Input name={getFormField("strongly.typed.field")} />;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment