optional react useState types with jsdoc, typescript checkjs (javascript)

Viewed 4166

using typescript's jsdoc support to type the following javascript code:

const [optionalNumber, setOptionalNumber] = useState(null)

const handleClick = () => {
  setOptionalNumber(42) 
  //          ^-- Argument of type '42' is not assignable to parameter of type 'SetStateAction<null>'
}

the way i currently get around this works but is a bit ugly:

const [optional, setOptional] = useState(
  /** @type {number|null} */ (null)
)

how can i accomplish this without using casting? i want optional to have a type of null | number, and setOptional to only accept null | number as an argument.

codesandbox demonstrating this:
https://codesandbox.io/s/optimistic-villani-kbudi?fontsize=14

2 Answers

Assuming that your component relies on the inital state of the optional state being the null value (rather than undefined), one solution would be to explicitly specify the state hooks type as a union type of both number and null like so:

// Allows initial value to be null, and number to be subsequently set 
const [optional, setOptional] = useState<number | null>(null);

// optional === null

setOptional(42);

Alternatively, if your component does not distingush between undefined or null for the inital optional state value, then the following would work:

const [optional, setOptional] = useState<number>();

// optional === undefined

setOptional(42);

I think you can define an initial value with the correct union type and pass it to useState.

It would be something like this:

/**
* @type {number | null}
*/
const initValue = 42;
const [optionalNumber, setOptionalNumber] = useState(initValue)
Related