1

I have basic select component like this.

import { Controller } from "react-hook-form";
import Select, { StylesConfig } from "react-select";
//..

const [universe, setUniverse] = useState<SetStateAction<TOption | unknown>>(null);

<Controller
    name="universe_id"
    control={control} // this control is imported from react-hook-form nothing special
    rules={{ required: true }}
    render={({ field }) => (
        <Select
            {...field}
            value={universe}
            onChange={handleUniverseChange}
            options={universeOptions}
            styles={selectStyles as StylesConfig}
        />
    )}
/>

And TOption type

export type TOption = {
  label: string | number;
  value: string | number;
};

Problem is that I can't set correct type for change handler value.

const handleUniverseChange = (item: unknown ) => {
    setUniverse(item);
    setValue("universe_id", item.value); // object type is unknown
};

Try to use TOption type for item also does not work.

const handleUniverseChange = (item: TOption) => {

Getting error in this line

<Select
    {...field}
    value={universe}
    onChange={handleUniverseChange}

Error: Type "(item: TOption) => void" can't assign for "(newValue: unknown, actionMeta: ActionMeta) => void".

2
  • Are you using any frontend UI framework like Antd or MUI ?? Commented Jul 8, 2022 at 5:36
  • @SujithSandeep using MUI Commented Jul 8, 2022 at 5:45

4 Answers 4

2

Fixed with type assertions and additional variable.

const handleUniverseChange = (item: TOption | unknown) => {
    setUniverse(item as TOption);
    const val = item as TOption;
    setValue("universe_id", val.value as string);
};
Sign up to request clarification or add additional context in comments.

Comments

0

The options should be in array and not in object. Kindly try the below code,

export type TOption = [{
  label: string | number;
  value: string | number;
}];

5 Comments

Wrong. Error in this line setValue("universe_id", item.value); Value does not exist in type TOption
Where does that item comes from ?. Are you creating state or something like that ?
It's coming from react-select. I'm not creating a state.
Did you try what I have mentioned in the answer ??
I tried everything which you mentioned.
0

I think the problem here lies with useState generic - unknown "dominating" TOption. If SetStateAction<...> is intended, change the unknown to null:

const [universe, setUniverse] = useState<SetStateAction<TOption | null>>(null);

if SetStateAction<...> is not intended:

const [universe, setUniverse] = useState<TOption | null>(null);

and then try

const handleUniverseChange = (item: TOption) => {
   ...
}

EDIT

The type is inferred from the passed options so make sure it is clear that your passed options are of the desired type (f.ex. TOption[])

export type TOption = {
    label: string | number;
    value: string | number;
};

const universes: TOption[] = [
    { label: "test", value: 0 },
    { label: "test2", value: 1 },
];

const App = () => {
    const handleChange = (item: TOption | null) => {
        if (!item) return;

        console.log(item); // {label: ..., value: ...}
    };

    return <Select onChange={handleChange} options={universes} />;
};

9 Comments

When I change paremeter in function handleUniverseChange differ from unknown, I'll get an error from this line onChange={handleUniverseChange} Error: Type "(item: TOption) => void" can't assign for "(newValue: unknown, actionMeta: ActionMeta) => void".
If I set there as parameter unknown | TOption then i get an error in this line setValue("universe_id", item.value); Error is -> object type is unknown
Changing the type in your use state call makes no difference?
yup, exactly.[5 symbols]
I tried myself and you are right. I see it infers the type based on the items passed, so i managed to get it accept (item: TOption | null) => void. So make sure your universe items are declared as an array of TOption and your state as TOption | null, then it should work without type assertions.
|
0

The SetStateAction is not required here.

Change the handler to

  const handleUniverseChange = (item: TOption | null )  => {}

Having said that, TOption feels very wrong. You are making your life difficult by saying label and value can be string | number.

type TOption = {
  label: string | number;
  value: string | number;
};

Also, i recommend you assign a default value instead of null here

  const [universe, setUniverse] = useState<TOption | null>(null);

Having nulls floating around is never a good idea.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.