I have a problem with the reduce
method in TypeScript:
const items = {a: 10, b:20, c: 30}
const itemsTotal = Object.keys(items).reduce((accumulator: number, key: keyof typeof items ) => {
return accumulator items[key]
}, 0)
I keep receiving the Typescript error:
Argument of type '(accumulator: number, key: "a" | "b" | "c") => number' is not assignable to parameter of type '(previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string'.
Types of parameters 'accumulator' and 'previousValue' are incompatible.***
It seems that I need to define the type of the reduce
method, but how?
CodePudding user response:
Object.keys
returns a string[]
, so you can't apply a reducer function that expects a keyof typeof items
to it.
You could use a type assertion, since you know it's valid:
const items = {a: 10, b:20, c: 30};
const itemsTotal = Object.keys(items).reduce((accumulator, key) => {
return accumulator items[key as keyof typeof items];
}, 0);
...but you don't need the key anyway, just use Object.values
:
const items = {a: 10, b:20, c: 30};
const itemsTotal = Object.values(items).reduce((accumulator, value) => {
return accumulator value;
}, 0);
(But frankly I'd just use a simple loop.)
CodePudding user response:
Not the cleanest solution but you can use this snippet:
const items = { a: 10, b: 20, c: 30 }
const itemsTotal = Object.keys(items).reduce((accumulator, key) => {
return accumulator items[key as keyof typeof items]
}, 0)
Key point is to cast key
to keyof typeof items
CodePudding user response:
Define your items as a Record of string
to number
. It will be clear for the reduce
method that the item is a number
.
const items: Record<string, number> = {a: 10, b: 20, c: 30}
const itemsTotal = Object.keys(items).reduce((accumulator: number, key: string) => {
return accumulator items[key];
}, 0)
You can also skip the braces in the reduce
body.
Object.keys(items).reduce((acc: number, key: string) => acc items[key], 0)
Even more, you can skip the type designations in the reduce
because your items
are already defined as numbers in the Record
.
Object.keys(items).reduce((acc, key) => acc items[key], 0)
Edit
You can skip the accumulator initialization. reduce
starts from the first item in such a case.
Object.values(items).reduce( (acc, item) => acc item )
The fastest solution is with for
of
because there are no function calls:
let sum = 0
for (const item of Object.values(items)) {
sum = item;
}