If I have this code:
import { useState } from "preact/hooks";
export default function Test() {
const [state, setState] = useState(null);
setState('string');
}
Then I get this error:
Argument of type 'string' is not assignable to parameter of type '(prevState: null) => null'.deno-ts(2345)
I understand that it expects me to use the same value type of the initial type. However if the initial value is an actual literal like number:
- const [state, setState] = useState(null);
+ const [state, setState] = useState(1);
Then the error is:
Argument of type 'string' is not assignable to parameter of type 'number | ((prevState: number) => number)'.deno-ts(2345)
Reading What is prevState in ReactJS? or Hooks – Preact Guide doesn't help me understand:
- What does
((prevState: null) => null) | nullmean? - Why is the first case the required type not
null | ((prevState: null) => null)? - How can I use multiple type? For example, the initial value is 1 or null, but I then set the value to
'string'afterward?
Although your question is partly answered, I think your second question is still not answered. So I will still submit this one:
Answer to the three questions:
React expects either a new state value or a state updater function. So since the type of your state is inferred to be
null, TS compiler is simply complaining that it would either expectnull(new state value) or((prevState: null) => null) | null(state updater function). This method should return a new value based on the previous value. Docnulltype in unions is usually merged into other types.Look at the below code.
The error is Type 'string' is not assignable to type 'number'. and not Type 'string' is not assignable to type 'number | null'.
Now if we write something like the below:
The error will be:
As you can see there is no omitting of
nullas there is no union.Playground Link for the above
This is a trivial example of what is happening above. And when the code is changed to:
The error is as expected and now includes the
numberpart of the union:'number | ((prevState: number) => number)'Edit: If you are keen on getting
nullin your error, depending on the version of TS involved you can tweak it.The below playground is using TS
4.x.x, and I can enable/disablestrictNullChecksby clicking on TS Config button. Once you enablestrictNullChecksPlayground
strictNullChecksdoes what it says. It starts includingnull( andundefined) in your checks (in this case a union)Doc