title: Typescript - Properly typing a map of functions that have bind run on them
body: <p>I'm trying to setup typings that allow me to have code completion for a set of functions in a map that have the same variable bound to them without having to manually declare an interface describing the output. </p>
  
  <p>I can do this with a single function just fine (see the <code>performBind</code> typings below), and I can get the typings to identify the key inside the map and know that it's a function, but it always has the signature <code>(...args: any[]) =&gt; void</code></p>
  
  <pre class="lang-ts prettyprint-override"><code>
  // Removes the first param from a tuple of params
  type Tail&lt;T extends any[]&gt; =
    ((...args: T) =&gt; any) extends ((head: any, ...tail: infer R) =&gt; any) ? R : never;
  
  // The input to the map function type
  type ActionMapping&lt;A, F extends (...args: any[]) =&gt; void&gt;  = {
    [key in keyof A]: F
  };
  
  // The output from the map function type.
  type PostActionMapping&lt;A, F extends (...args: any[]) =&gt; void&gt;  = {
    [key in keyof A]: (...args: Tail&lt;Parameters&lt;F&gt;&gt;) =&gt; ReturnType&lt;F&gt;
  };
  
  // Single binding function - basically what is being applied to each function in a map, but for a single function
  function performBind&lt;F extends (...args: any) =&gt; any&gt;(func: F, binding: any): (...args: Tail&lt;Parameters&lt;F&gt;&gt;) =&gt; ReturnType&lt;F&gt; {
    return func.bind(null, binding);
  }
  
  // Mapping function
  function associateActions&lt;A, F extends (...args: any[]) =&gt; void&gt;(actions: ActionMapping&lt;A, F&gt;, toBind: number): PostActionMapping&lt;A, F&gt; {
    const actionList: PostActionMapping&lt;A, F&gt; = {} as  PostActionMapping&lt;A, F&gt;  ;
    Object.keys(actions).forEach(key =&gt; {
  
      if (typeof actions[key as keyof A] === 'function') {
  
        actionList[key as keyof A] =  performBind(actions[key as keyof A], toBind);
      }
    });
  
    return actionList;
  }
  
  // Single function mapping test
  const testing = performBind((numberArg: number, stringArg: string): string =&gt; {
    return `${numberArg} - ${stringArg}`;
  }, 3);
  
  testing('test'); // types as `testing(stringArg: string): void` - Correct!
  
  
  // My action map
  const myActions = {
    testing: (numberArg: number, stringArg: string): string =&gt; {
      return `${numberArg} - ${stringArg}`;
    },
  };
  
  // Testing w/ my map above
  const mapped = associateActions(myActions, 3);
  mapped.testing('test'); // types as `mapped.testing(...args: any[]): void` - Missing the typing
  
  </code></pre>
  
  <p>As noted, the ones coming out of the map are all typed as <code>(...args: any[]):void</code>. Everything <em>works</em>, but it'd be great of course to have the autocomplete and typings correct.</p>