Home > OS >  Identity partial function with Typescript
Identity partial function with Typescript

Time:06-25

Suppose I have a function partial(), that takes a callable and arguments that have to be passed to it, and prefills the first argument of the callable.

How should I annotate its parameters for the type check to work, no matter which callable I pass to it.

function foo(a: string, b: number, c: string) {
  console.log('foo', a, b, c)
}

function bar(a: string) {
  console.log('bar', a)
}

function partial(callable, ...args) {
  callable('identity', ...args)
}

If it helps, this is what I am currently trying, but doesn't quite work:

  partial<T>(callable: (...args: [string, ...T[]]) => void, ...args: T[]) {
    callable('partial a', ...args);
  }

CodePudding user response:

You want to represent the rest of the arguments as a tuple type, so that the compiler keeps track of the number and order of the different argument types. It looks like this:

function partial<T extends any[]>(
  callable: (...args: [string, ...T]) => void, ...args: T
) {
  callable('identity', ...args)
}

So the type parameter T is already an arraylike type. When you call partial():

partial(foo, 1, "okay")  // "foo",  "identity",  1,  "okay" 
// function partial<[number, string]>(callable: 
//   (args_0: string, args_1: number, args_2: string) => void, 
//  args_0: number, args_1: string): void

partial(bar); // "bar",  "identity" 
// function partial<[]>(callable: (args_0: string) => void): void

You can see that for foo, T gets inferred as [number, string], while for bar, T gets inferred as [] (the empty tuple).

Playground link to code

  • Related