skip to Main Content

This is ok:

const [foo, setFoo] = useState<string>()

This is not:

const [boo, setBoo] = useState<string>(undefined)

Argument of type ‘undefined’ is not assignable to parameter of type ‘string | (() => string)’

I think they have the same meaning, though – useState with no arguments is the same as useState(undefined).

Is it simply that TypeScript can’t detect this for some reason?

2

Answers


  1. Because the DefinitelyTyped definition is overloaded with 2 signatures for useState, where one of them has no arguments:

    // with argument
    function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
    // no argument
    function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
    

    If you want the argument definition to allow for an undefined you need to explicitly define it like so:

    const [boo, setBoo] = useState<string|undefined>(undefined)
    
    Login or Signup to reply.
  2. useState<string>() is a convinence shorthand for useState<string|undefined>(undefined)

    The typing is here

    function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
    // convenience overload when first argument is omitted
    // ...
    function useState<S = undefined>(): [S | undefined, Dispatch<SetStateAction<S | undefined>>];
    
    

    As stated in the code comment, this is just convinience, not an omission but put there on purpose.

    Do not use this is your state must strictly be a string as omiting the argument makes undefined to also be allowed.

    Sidepoint: this also allows useState() with no argument or type argument, which results in a state object that can only be undefined

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search