I'm trying to filter my array of objects in react type script. Got this error.Here is my interface , state and function
TS2345: Argument of type '(prev: IBudget, current: IBudget) => IBudget | undefined' is not assignable to parameter of type '(previousValue: IBudget, currentValue: IBudget, currentIndex: number, array: IBudget[]) => IBudget'.
Type 'IBudget | undefined' is not assignable to type 'IBudget'.
Type 'undefined' is not assignable to type 'IBudget'.
export interface IBudget {
title?:string,
price?:number,
date?: Date,
}
const [expenses,setExpenses] = useState<IBudget[]>([])
if (!isEmpty(expenses)){
const max = expenses.reduce((prev , current)=> {
if( prev !== undefined) {
if (prev.price !== undefined && current.price !== undefined){
return (prev.price > current.price) ? prev : current
}
}
})
}
CodePudding user response:
This is probably happening because you didn't pass an initial value to the reduce
function, and given your implementation you could pass the first argument of the expenses
array
const max = expenses.reduce((prev, current) => {
if (prev !== undefined) {
if (prev.price !== undefined && current.price !== undefined) {
return prev.price > current.price ? prev : current;
}
}
}, expenses[0]);
after you do that you probably will have another error saying that the previous
or the current
types do not match with undefined
. And this would be because you have if's
that could potentially not be entered right? and if that happens your code will return undefined
to the next interaction.
In order to fix that you need to make sure that some value is returned to the next iteration, as below:
const max = expenses.reduce((prev, current) => {
if (prev !== undefined) {
if (prev.price !== undefined && current.price !== undefined) {
return prev.price > current.price ? prev : current;
}
}
// here you might have to adjust to your needs
return current;
}, expenses[0]);
CodePudding user response:
The type definition of reduce
will automatically set the return type to the type of array - number[]
is assumed to reduce to number
.
You can override this by passing a initialValue
of the same type as you expect the return to be, or by setting it using generics (or both):
[1,2,3].reduce<number | string>(...)
In your case, it's unclear what your desired result is. Do you intend to have undefined
possibly be returned? If not, you need to handle the cases where your 2 if
statements do not pass, since the absence of a return
is what is causing the undefined
type inference.
If you do want the possibility of undefined, you could simply set the type, and pass in an initialValue
:
const max = expenses.reduce<IBudget | undefined>((prev , current)=> {
if( prev !== undefined) {
if (prev.price !== undefined && current.price !== undefined){
return (prev.price > current.price) ? prev : current
}
}
}, undefined)