1

I have a function with declared type. I plan to use a partial version of this function. But I need to declare the variable first for the partial version.

I can copy the signature, omitting the first parameter.
While it works and do type checks, I would like to automate this.

This is how I want to use it:

function myFunc(a: number, b: number): number {
    return a + b
}

let partFunc: PartialFunc<typeof myFunc>

// later
partFunc = (b) => myFunc(42, b)

And I don't know if it's possible to create PartialFunc<Func> generic.

I tried this approach

interface Func1<T1, TRes> {
    (a: T1): TRes
}
interface Func2<T1, T2, TRes> {
    (a: T1, b: T2): TRes
}
interface PartialFunc<TFunc extends Func2<T1, T2, TRes>, T1=any, T2=any, TRes=any> extends Func1<T2, TRes>{}

or the same with generic types:

type F1<T1, TRes> = (a: T1) => TRes
type F2<T1, T2, TRes> = (a: T1, b: T2) => TRes
type PF<Func extends F2<T1, T2, TRes>, T1=any, T2=any, TRes=any> = F1<T2, TRes>

But this still requires me to specify all the types:

let partFunc: PF<typeof myFunc, number, number, number>

otherwise I have any types.

While this enforces the type check, e.g. it will not accept PF<typeof myFunc, number, number, string>, I would like to avoid writing types again.

Basically I want to say to TS Take the signature of this function and remove first param

Is there any solution for this?

Context of this task - I have a react-redux application, and I want to bind the parameter from store to action dispatcher.

Igor
  • 3,129
  • 1
  • 21
  • 32

1 Answers1

7

In TypeScript 2.8 and up you can use conditional types to do this, by leveraging the awesome type inference in conditional types feature. Here's how you might use it in this particular situation:

type RemoveFirstParamFromTwoParamFunction<F extends (a: any, b: any)=>any> =
  F extends (a: any, b: infer B) => infer R ? (b: B) => R : never

function myFunc(a: number, b: number): number {
    return a + b
}

let partFunc: RemoveFirstParamFromTwoParamFunction<typeof myFunc>;
partFunc = (b) => myFunc(42, b);

Notice how this only works on concrete functions of exactly two required parameters. If you need it to work on possibly-generic functions of more/fewer possibly-optional parameters, you will have to work harder to get it done by enumerating cases and testing thoroughly. That's because TypeScript currently (as of TypeScript 2.8) lacks a way to programmatically access function parameters. The exact type of RemoveFirstParam<> you need depends on your use case.

Hope that helps. Good luck.

jcalz
  • 264,269
  • 27
  • 359
  • 360