Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

I want to put nested type names in the first argument of setValue in react-hook-form

I want to do
I want to avoid typescript error when "profile.firstName" is passed as the second argument to the function onChange.

Error Description
Arguments of type ‘"profile.firstName"’ cannot be assigned to parameters of type ‘keyof User’. ts(2345)

Passing "id", "groupName", and "description" as the second argument to onChange does not cause an error.
However, if "profile.firstName" is passed, an error occurs.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


import { useForm } from 'react-hook-form';

import type { CustomNextPage } from 'next';

import { Button, Input } from 'components/Forms';
import { Box } from 'components/Layouts';

export interface User {
  id?: string;
  groupName?: string;
  description?: string;
  profile?: {
    firstName?: string;
    lastName?: string;
    email?: string;
  };
}

const Filter: CustomNextPage = () => {
  const { handleSubmit, setValue, watch } = useForm<User>();
  type P = keyof User;

  const onChange = (value: string, key: P) => {
    setValue(key, value);
  };

  return (
    <>
      <Box>
        <Input onChange={(e) => onChange(e.target.value, 'id')}>ID</Input>
        <Input onChange={(e) => onChange(e.target.value, 'groupName')}>GroupName</Input>
        <Input onChange={(e) => onChange(e.target.value, 'description')}>Description</Input>
        <Input onChange={(e) => onChange(e.target.value, 'profile.firstName')}>FirstName</Input>
        <Box>
          <form>
            <Button type="submit"></Button>
          </form>
        </Box>
      </Box>
    </>
  );
};

export default Filter;


        <Input
          onChange={(e) =>
            onChange(
              {
                ...watch().profile,
                firstName: e.target.value,
              },
              'profile',
            )
          }
        >
          FirstName
        </Input>

Arguments of type ‘{ firstName: string; lastName?: string | undefined; email?: string | undefined; }’ cannot be assigned to parameters of type ‘string’. ts(2345)

        <Input
          onChange={(e) =>
            setValue(
              {
                ...watch(),
                profile: {
                  ...watch().profile,
                  firstName: e.target.value,
                },
              },
              'profile',
            )
          }
        >
          FirstName
        </Input>

The argument of type ‘{ profile: { firstName: string; lastName?: string | undefined; email?: string | undefined; }; id?: string | undefined; groupName?: string | undefined; description? undefined; description?: string | undefined; }’ argument of type ‘"id" | "groupName" | "description" | "profile" | "profile.firstName" | "profile.lastName" | "profile.email "profile.email"’ parameters cannot be assigned to parameters of type ‘"id" | "groupName" | "description" | "profile.firstName" | "profile.lastName" | "profile.email"’. ts(2345)

>Solution :

User has a profile property, which is an object that has the property firstName. So this approach is not going to work.

You could do something like:

<Input onChange={(e) => onChange({
    ...value.profile,
    firstName: e.target.value,
}, 'profile')}>FirstName</Input>

(I’m assuming useForm also returns a value?)

This is a little funky though. Also, onChange.value is no longer just a string.


I think you’re sort of drowning in ‘convenience’ functions.

Maybe just do:

<Input onChange={(e) => setValue("profile", {
    ...value.profile,
    firstName: e.target.value,
})}>FirstName</Input>

And maybe just split this off to a setProfileFirstName funtion.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading