reactjstypescriptdispatch

Typescript React Dispatch


// MyComponent property
setSelected: Dispatch<SetStateAction<string>> | Dispatch<SetStateAction<string[]>>

// App.tsx
const [selected, setSelected] = useState<string[]>(['x'])

<MyComponent setSelected={setSelected} />

// MyComponent
setSelected(['x'])
// type error: Argument of type 'string[]' is not assignable to parameter of type 'SetStateAction<string> & SetStateAction<string[]>

I have a setSelected function. It will take string or string list and save it. But both of them give type error. What is the reason?

Also '|' as it appears in the error message indicates the '&' symbol as a symbol. I couldn't understand that either.

Another Type:

// MyComponent property
setSelected: Dispatch<SetStateAction<string | string[]>>

// App.tsx
const [selected, setSelected] = useState<string[]>(['x'])

<MyComponent setSelected={setSelected} />
// type error: Type 'Dispatch<SetStateAction<string[]>>' is not assignable to type 'Dispatch<SetStateAction<string | string[]>>

Solution

  • When you define a union of functions, typescript resolves the argument as the intersection of of the function arguments.

    For example (arg:string)=>{} | (arg:number)=>{} will be considered as (arg:string & number)=>{}.

    React dispatch is defined as type Dispatch<A> = (value: A) => void; so it is a function.

    SetStateAction is also possible a function, you can have callback version of setState.

    So rather than

    setSelected: Dispatch<SetStateAction<string>> | Dispatch<SetStateAction<string[]>>
    
    

    you can use

    setSelected: Dispatch<SetStateAction<string|string[]>>
    
    

    So the union is applied to the generic which represents the arguments expected by setState.