Reputation: 6476
When I define the following function:
export const filterAndCast = <T, U>(
items: T[],
predicate: Predicate<T>,
cast: (x: T) => U,
) => items
.reduce(
(p, c) => [
...p,
...(predicate(c) ? [cast(c)] : []),
],
[],
);
I'd expect to have U[]
returned. But I instead get any[]
.
How can I fix this?
Upvotes: 0
Views: 36
Reputation: 2054
You just need to implicitly type the generic param of reduce()
.
// Assuming your predicate is this
type Predicate<T> = (x: T) => boolean;
export const filterAndCast = <T, U>(
items: T[],
predicate: Predicate<T>,
cast: (x: T) => U
) => items
.reduce<U[]>( // Provide <U[]> here
(p, c) => [
...p,
...(predicate(c) ? [cast(c)] : []),
],
[],
);
// Keep numbers or string that can be casted to numbers
const results = filterAndCast(
[1, 3, 'asd', '1', '2', '3'],
(x) =>
(typeof x === 'number') ||
(typeof x === 'string' && !isNaN(parseFloat(x))),
(x) => typeof x === 'number' ? x : parseFloat(x)
);
As a side note you could refactor the reduce()
, so it only spreads the array when the predicate returns true
.
items.reduce<U[]>((p, c) => (predicate(c) ? [...p, cast(c)] : p), [])
Upvotes: 1
Reputation: 5760
How about this?
export const filterAndCast = <T, U>(
items: T[],
predicate: (c:T) => boolean,
cast: (x: T) => U,
) => items
.reduce(
(p, c) => [
...p,
...(predicate(c) ? [cast(c)] : []),
],
[],
);
const results = filterAndCast([1, 2, 3], x => x % 2 === 0, x => Number(x))
results.forEach(el=> console.log(typeof el));
Upvotes: 1