Reputation: 1072
Trying to write a basic reducer to return an array of (value of) a key from an array of objects. Some of the key can be missing or undefined.
My code:
const data = [{Key: 56}, {Key: undefined}, {}, {Key: 44}]
const keys = data.reduce((prev, curr) => {
if (curr.Key) {
return [...prev, curr.Key];
} else return prev;
}, []);
It works fine as a plain JS but the TS compiler does not like it. Playground Link
How to fix this? mainly what am I doing wrong? I am a TS noob.
Error:
No overload matches this call.
Overload 1 of 3, '(callbackfn: (previousValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentIndex: number, array: ({ Key: number; } | { ...; } | { ...; })[]) => { ...; } | ... 1 more ... | { ...; }, initialValue: { ...; } | ... 1 more ... | { ...; }): { ...; } | ... 1 more ... | { ...; }', gave the following error.
Argument of type '(prev: never[], curr: { Key: number; } | { Key: undefined; } | { Key?: undefined; }) => number[]' is not assignable to parameter of type '(previousValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentIndex: number, array: ({ Key: number; } | { ...; } | { ...; })[]) => { ...; } | ... 1 more ... | { ...; }'.
Types of parameters 'prev' and 'previousValue' are incompatible.
Type '{ Key: number; } | { Key: undefined; } | { Key?: undefined; }' is not assignable to type 'never[]'.
Type '{ Key: number; }' is missing the following properties from type 'never[]': length, pop, push, concat, and 26 more.
Overload 2 of 3, '(callbackfn: (previousValue: never[], currentValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentIndex: number, array: ({ Key: number; } | { Key: undefined; } | { Key?: undefined; })[]) => never[], initialValue: never[]): never[]', gave the following error.
Argument of type '(prev: never[], curr: { Key: number; } | { Key: undefined; } | { Key?: undefined; }) => number[]' is not assignable to parameter of type '(previousValue: never[], currentValue: { Key: number; } | { Key: undefined; } | { Key?: undefined; }, currentIndex: number, array: ({ Key: number; } | { Key: undefined; } | { Key?: undefined; })[]) => never[]'.
Type 'number[]' is not assignable to type 'never[]'.
Type 'number' is not assignable to type 'never'.
Upvotes: 9
Views: 8596
Reputation: 173
You need to specify the type of the second argument of reduce
function.
Try this
const data = [{key: 56}, {key: undefined}, {}, {key: 44}]
const keys = data.reduce((keys, current) => {
if (current.key) {
return [...keys, current.key];
} else return keys;
}, [] as number[]);
Edit: I rushed the answer before, also to improve the readbility of the code, I suggest you to make some changes, like name the property key
instead of Key
, and some better naming for the parameters of the reduce
function
Upvotes: 4
Reputation: 191976
Assign the type of the accumulator ([]
) as number[]
(TS playground):
const keys = data.reduce((prev, curr) => {
if (curr.Key) {
return [...prev, curr.Key];
} else return prev;
}, [] as number[]);
Upvotes: 15