Argument of type '{ [x: string]: string; }' is not assignable to parameter of type

Viewed 271

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")}
          />
  )
0 Answers
Related