I created a custom React hook "useForm" in TypeScript. I wanted to be more type-specific so in getTextChangeHandler, I require the parameter to be a key within the state, as follows:
useForm.ts
import { ChangeEvent, useReducer } from "react";
const useForm = <FormStateType>(initialValues: FormStateType) => {
type FieldName = keyof FormStateType;
function reducer(prevState: FormStateType, updates: Partial<FormStateType>) {
return {
...prevState,
...updates,
};
}
const [state, dispatch] = useReducer(reducer, initialValues);
function update(updates: Partial<FormStateType>) {
dispatch(updates);
}
function reset() {
dispatch(initialValues);
}
function getTextChangeHandler(fieldName: FieldName) {
return (e: ChangeEvent<HTMLInputElement>) => {
update({ [fieldName ]: e.target.value });
};
}
return { state, update, reset, getTextChangeHandler };
};
export default useForm;
but I keep getting this error in the update({ [fieldName ]: e.target.value }) call:
Argument of type '{ [x: string]: string; }' is not assignable to parameter of type 'Partial<FormStateType>'. TS2345
It may be worth noting that if I change FormStateType to FormStateType | Record<string, any> to the type of updates and the function signature of update, the error is miraculously gone but is smelly to me because I believe it's unnecessary.
Example usage of useForm.ts:
import useForm from "../hooks/useForm";
import TextField from "@mui/material/TextField";
export default function AddressForm() {
const { getTextChangeHandler, reset, state, update } = useForm({
firstName: "",
lastName: "",
address1: "",
address2: "",
city: "",
state: "",
zip: "",
country: "",
});
return (
<TextField
value={state.firstName}
onChange={getTextChangeHandler("firstName")}
/>
)