I am making a reusable, dynamic form component using react-hook-form's useFieldArray hook and I am having problems correctly adding the type for field.
To set-up the form I have added a type and some defaultValues:
export type NamesArray = { name: string; required: boolean }[];
export type FormValues = { randomFormValue: string; namesArray: NamesArray };
const defaultValues = {
namesArray: [{ name: "Me", required: true }]
};
Now, when I use my reusable form component, <NamesForm /> it should always know to use the namesArray part of the form for that component such that I should be able to do:
type Props<T> = {
control: Control<T>;
register: UseFormRegister<T>;
};
export function NamesForm<T extends NamesArray>({
control,
register
}: Props<T>) {
const { fields, append } = useFieldArray<T, "namesArray", "id">({
control,
name: "namesArray"
});
return (
<>
{fields.map((field, index) => {
return {field.required && <input {...register(`namesArray.${index}.name` as const)} />};
})}
<button type="button" onClick={() => append({})}>
Append
</button>
</>
);
}
Where, in order to make the component reusable, I have used generic props.
My problem is that even though I have explicitly said that my generic T should contain a namesArray, TS can't seem to pick that up and gives me the error:
Type 'string' does not satisfy the constraint 'ArrayPath'.
And it is not enough for me to not define the type of field because I would like to use field's properties such as required.
Code sandbox: https://codesandbox.io/s/controlled-field-array-forked-vooe9w?file=/src/NamesForm.tsx:139-214