Reputation: 12032
I'm trying to get better with FP but struggling how to deal with typing generic "curry" functions.
For example, I've written a "Curry" version of reduce:
const reduce = <S, R>(fn: (result: R, obj: S, i?: number, arr?: S[]) => R, init: R) =>
(objects: S[]) =>
objects.reduce(fn, init);
const numToSum: number[] = [1,2,3,5,8,13];
const result = reduce((sum, n) => sum + n, 0)(numToSum);
The problem is that typescript obviously can't know the type of S
until you actually call the curry function with numToSum
.
It's more obvious when you see it without the curry call:
const sumNumbersFn = reduce((sum, n) => sum + n, 0);
In this case you can fix this by typing the arguments of the function itself with n: number
or explicitly setting the generic parameters <number[], number>
.
The former seems reasonable, but what I'm running into is that as things get more complex, I'm constantly having to provide generic signature.
I'm wondering if I am missing something, and it is actually possible to get typescript to "infer" the types from the later function calls?
Going back to the first example:
const result = reduce((sum, n) => sum + n, 0)(numToSum);
It seems like the compiler actually SHOULD have all the information needed to infer types.
Maybe my types are just off?
Here's a more concrete/full example of the problem I'm running into
Upvotes: 4
Views: 534
Reputation: 1337
All you have to do is to declare a function which you return from select
function as generic:
function select<T, S>(sFn: (obj: T) => S) {
function computation<G>(fn: (obj: S) => G) {
return (obj: T) => fn(sFn(obj));
}
return computation;
}
P.S: I don't know why such kind of syntax doesn't work in TS playground:
const select = <T, S>(sFn: (obj: T) => S) => <G>(fn: (obj: S) => G) => {
return (obj: T) => fn(sFn(obj));
}
Maybe because of some TS config settings. Thus I wrote the solution as a function declaration instead of a function expression.
Upvotes: 3