I am learning TypeScipt and I have already managed to come to a dead end and TS won't let me go any further. So I have defined my interfaces as below:
export interface Test {
id: number;
date: Date;
location: string;
elements?: Element[];
}
export interface Element {
id: string;
name: string;
referenceFrom: number | string;
referenceTo: number | string;
result: number | string;
}
I am then using one of the interfaces for below useState hook:
const [currentTest, setCurrentTest] = useState<Test | null>(null);
And at one point I am trying to use setCurrentTest
and the prevState
inside of it, however TypeScript won't let me do that and I am getting below error:
Argument of type '(prev: Test | null) => { elements: any[]; id?: number | undefined; date?: Date | undefined; location?: string | undefined; }' is not assignable to parameter of type 'SetStateAction<Test | null>'.
Type '(prev: Test | null) => { elements: any[]; id?: number | undefined; date?: Date | undefined; location?: string | undefined; }' is not assignable to type '(prevState: Test | null) => Test | null'.
Call signature return types '{ elements: any[]; id?: number | undefined; date?: Date | undefined; location?: string | undefined; }' and 'Test | null' are incompatible.
The types of 'id' are incompatible between these types.
Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.ts(2345)
The function that I am using this setCurrentTest
in looks like that:
const handleSubmitForm = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const { id, name } = results;
const referenceFrom = Number(results.referenceFrom);
const referenceTo = Number(results.referenceTo);
const result = Number(results.result);
if (
id &&
name &&
referenceFrom > 0 &&
referenceTo > 0 &&
referenceFrom < referenceTo &&
result > 0
) {
setCurrentTest((prev) => ({...prev, elements: [...prev.elements, { id, name, referenceFrom, referenceTo, result }] }));
}
};
What I understand from this is that the optional null
in the Test | null
is causing this issue. Also in the interface Element
there is this optional elements?
which is also causing the issue because it can also be undefined
.
So how can I escape this?
CodePudding user response:
If you can't add an initial state to avoid having the null, you can make a validation so it only tries to spread the previous state if it's not null. Like this:
setCurrentTest((prev: any) => {
if (prev) {
return {...prev, elements: [...prev.elements, {id, name, referenceFrom, referenceTo, result}]};
}
return {elements: [{id, name, referenceFrom, referenceTo, result}]};
});