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:
((prevState: null) => null) | null
mean?null | ((prevState: null) => null)
?'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 expect null
(new state value) or ((prevState: null) => null) | null
(state updater function). This method should return a new value based on the previous value. Doc
null
type in unions is usually merged into other types.
Look at the below code.
let x : null| number = 'string';
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:
let y : null = 'string';
The error will be:
As you can see there is no omitting of null
as there is no union.
This is a trivial example of what is happening above. And when the code is changed to:
const [state, setState] = useState(1);
The error is as expected and now includes the number
part of the union:
'number | ((prevState: number) => number)'
const [val,setVal] = useState<number | null | string | boolean>(null)
Edit:
If you are keen on getting null
in 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/disable strictNullChecks
by clicking on TS Config button. Once you enable strictNullChecks
strictNullChecks
does what it says. It starts including null
( and undefined
) in your checks (in this case a union)