title: Best way to inject a function using InversifyJS
body: <p>There's an <a href="https://github.com/inversify/InversifyJS/blob/master/wiki/recipes.md#injecting-dependencies-into-a-function" rel="nofollow noreferrer">official recipe</a> to inject a function using <a href="https://github.com/inversify/InversifyJS" rel="nofollow noreferrer">InversifyJS</a>. Basically, we define a helper function that will return a curried version of a given function <code>func</code> with all its dependencies resolved using <code>container.get(...)</code>:</p>
  
  <pre><code>import { container } from "./inversify.config"
  
  function bindDependencies(func, dependencies) {
      let injections = dependencies.map((dependency) =&gt; {
          return container.get(dependency);
      });
  
      return func.bind(func, ...injections);
  }
  
  export { bindDependencies };
  </code></pre>
  
  <p>And we use it like this:</p>
  
  <pre><code>import { bindDependencies } from "./utils/bindDependencies";
  import { TYPES } from "./constants/types";
  
  function testFunc(something, somethingElse) {
      console.log(`Injected! ${something}`);
      console.log(`Injected! ${somethingElse}`);
  }
  
  testFunc = bindDependencies(testFunc, [TYPES.something, TYPES.somethingElse]);
  
  export { testFunc };
  </code></pre>
  
  <p>I'd like to inject the function automatically, without explicitly provide it's dependencies to <code>bindDependencies</code>, maybe based on the function's parameters names. Something like this:</p>
  
  <pre><code>import { default as express, Router } from 'express';
  
  import { bindDependencies } from '../injector/injector.utils';
  
  import { AuthenticationMiddleware } from './authentication/authentication.middleware';
  import { UsersMiddleware } from './users/users.middleware';
  
  import { ENDPOINTS } from '../../../../common/endpoints/endpoints.constants';
  
  
  function getRouter(
      authenticationMiddleware: AuthenticationMiddleware,
      usersMiddleware: UsersMiddleware,
  ): express.Router {
      const router: express.Router = Router();
  
      const requireAnonymity: express.Handler = authenticationMiddleware.requireAnonymity.bind(authenticationMiddleware);
      const requireAuthentication: express.Handler = authenticationMiddleware.requireAuthentication.bind(authenticationMiddleware);
  
      router.route(ENDPOINTS.AUTHENTICATION)
          .put(requireAnonymity, authenticationMiddleware.login.bind(authenticationMiddleware))
          .delete(requireAuthentication, authenticationMiddleware.logout.bind(authenticationMiddleware));
  
      router.route(ENDPOINTS.USER)
          .put(requireAnonymity, usersMiddleware.register.bind(usersMiddleware))
          .post(requireAuthentication, usersMiddleware.update.bind(usersMiddleware))
          .delete(requireAuthentication, usersMiddleware.remove.bind(usersMiddleware));
  
      return router;
  }
  
  const router: express.Router = invoke(getRouter);
  
  export { router as Router };
  </code></pre>
  
  <p>Note in this case I just want to call the injected function once and get its return value, which is what I'm exporting, so maybe there's a better way to do this without wrapping the code in a function, but I though using <code>container.get(...)</code> directly outside of my composition root was not a good idea, as the dependencies for this module would not be clear and may be spread across all its lines. Also, exporting that function would simplify the tests. </p>
  
  <p>Going back to my issue, my <code>invoke</code> function looks like this:</p>
  
  <pre><code>function invoke&lt;T&gt;(fn: Function): T {
      const paramNames: string[] = getParamNames(fn);
  
      return fn.apply(null, paramNames.map((paramName: string)
          =&gt; container.get( (&lt;any&gt;container).map[paramName.toUpperCase()] ))) as T;
  }
  </code></pre>
  
  <p>For <code>getParamNames</code> I use one of the solutions proposed here: <a href="https://stackoverflow.com/questions/1007981/how-to-get-function-parameter-names-values-dynamically-from-javascript">How to get function parameter names/values dynamically from javascript</a></p>
  
  <p><code>(&lt;any&gt;container).map</code> is an object I create in my <code>inversify.config.ts</code> after creating my container, which links a string representation of all my dependencies' keys and the real key, regardless of its type (in this case, just <code>symbol</code> or <code>Function</code>):</p>
  
  <pre><code>const container: Container = new Container();
  
  container.bind&lt;FooClass&gt;(FooClass).toSelf();
  
  ...
  
  const map: ObjectOf&lt;any&gt; = {};
  
  (&lt;any&gt;container)._bindingDictionary._map
      .forEach((value: any, key: Function | symbol) =&gt; {
          map[(typeof key === 'symbol'
              ? Symbol.keyFor(key) : key.name).toUpperCase()] = key;
      });
  
  (&lt;any&gt;container).map = map;
  </code></pre>
  
  <p>Anyone knows if there's a better way to do this or if there's any important reason not to do it?</p>