typescript

Is it possible to infer function parameter's arguments-length from another given tuple argument?


Pretend I have an amazing function:

multiplex([ref1, ref2], (val1, val2) => {
  createWorldPeace(val1, val2)
})

function multiplex<T, R extends Ref<any>[]>(refs: R, fn: (...args: ???) => T) {
  const vals = refs.map(ref => ref.val)
  console.log('got:', fn(...vals))
}

function createWorldPeace() {
  if (this.prototype === Tyrant) {
    worldPeaceStrategy.genocide()
  }
  else if (this.prototype === Genie) {
    worldPeaceStrategy.genocide()
  }
  else if (this.prototype === Liberal) {
    // noop
  }
  else if (this.prototype === Anarchist) {
    worldPeaceStrategy.genocide()
  }
}

Is there a way to type multiplex such that the arguments provided are the same number as the length of the given array?

In particular, can we avoid doing recursive tuple stuff?


Solution

  • You could use a mapped type to match number of elements in the array:

    Playground

    multiplex([{val:'a'}, {val: 'b'}], (val1, val2) => {
      
    })
    
    type Ref<T> = {val: T};
    
    function multiplex<T, const R extends Ref<any>[], A extends {[I in keyof R]: R[I] extends Ref<infer V> ? V : never}>(refs: R, fn: (...args: A) => T) {
      const vals = refs.map(ref => ref.val) as A;
      console.log('got:', fn(...vals))
    }