Reputation: 12032
So... this might be hard to follow but here it goes...
I want to create a function f()
that accepts a function as it's parameter and returns a new function that has the same parameters excluding the first parameter (which can be concretely typed).
function f<R, A extends (s: string) => R>(func: A): () => R; // no extra params
function f<R, T1, A extends (s: string, a1: T1) => R>(func: A): (a1: T1) => R; // 1 extra
function f<R, T1, T2, A extends (s: string, a1: T1, a2: T2) => R>(func: A): (a1: T1, a2: T2) => R; // 2 extra
function f(func: (...x: any[]) => any) {
return (...x) => {
return func('hello', ...x); //call function. 'hello will always be passed as first param, followed by the rest
};
}
In this example, f()
should basically take any function where the first parameter is a string (s
) and return a new function with 0 to 2 parameters (a1
& a2
if present in passed function; s
will be excluded).
So if I were to pass:
function testFunc(x: string, y: number): number{
return x.length + y;
}
const x = f(testFunc);
I would expect x
to be type (a1: number) => number
. However, instead I'm getting (a1: {}) => {}
...
Is what I'm trying to do even possible?
Upvotes: 1
Views: 226
Reputation: 221004
You have too many free type parameters and it's messing up generic inference. The function should look like this (extra overloads omitted for brevity):
function f<R>(func: (s: string) => R): () => R;
function f<R, T1>(func: (s: string, a1: T1) => R): (a1: T1) => R; // 1 extra
function f(func: (...x: any[]) => any) {
return (...x) => {
return func('hello', ...x); //call function. 'hello will always be passed as first param, followed by the rest
};
}
function testFunc(x: string, y: number): number{
return x.length + y;
}
// x: (a1: number) => number
const x = f(testFunc);
Upvotes: 2