{"id":7516,"date":"2019-11-03T20:56:22","date_gmt":"2019-11-03T20:56:22","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=7516"},"modified":"2019-11-03T20:56:22","modified_gmt":"2019-11-03T20:56:22","slug":"inversify","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/inversify\/","title":{"rendered":"inversify"},"content":{"rendered":"<p>I wanted to use an IoC pattern\/library in a project I was working on (a node server application where I would slot in the specific implementations of the data and services at runtime).<\/p>\n<p>I cam across inversify, there may be other IoC&#8217;s for TypeScript, but this is the one I looked into and worked a treat for me.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nyarn add inversify reflect-metadata\r\n<\/pre>\n<p>You will need to enable <em>experimentalDecorators<\/em> and <em>emitDecoratorMetadata<\/em> within the tsconfig.json file.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&quot;experimentalDecorators&quot;: true,        \r\n&quot;emitDecoratorMetadata&quot;: true, \r\n<\/pre>\n<p>as per the invertsify documentation, we should also have the following tsconfig.json properties set<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n&quot;target&quot;: &quot;es5&quot;,\r\n&quot;lib&quot;: &#x5B;&quot;es6&quot;],\r\n&quot;types&quot;: &#x5B;&quot;reflect-metadata&quot;],\r\n&quot;module&quot;: &quot;commonjs&quot;,\r\n&quot;moduleResolution&quot;: &quot;node&quot;,\r\n<\/pre>\n<p>As is usual in C# (at least), the best way to work with IoC is to define an interface for our abstraction and then an implementation. However for inverisfy we also define a Symbol for the interfaces. So let&#8217;s assume we&#8217;re going to have a <em>Service<\/em> interface along with <em>RestService<\/em> and <em>WebsocketService<\/em>.<\/p>\n<p>First create your Service.ts file and here&#8217;s a simple example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ninterface Service {\r\n  call(data: string): void;\r\n};\r\n\r\nexport default Service;\r\n<\/pre>\n<p>Now let&#8217;s create a couple of implementations, RestService.ts<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport &quot;reflect-metadata&quot;;\r\nimport Service from &quot;.\/Service&quot;;\r\nimport { injectable } from &quot;inversify&quot;;\r\n\r\n@injectable()\r\nclass RestService implements Service {\r\n  call(data: string): void {\r\n    console.log(&quot;RestService called&quot;);\r\n  }\r\n}\r\n\r\nexport default RestService;\r\n<\/pre>\n<p>As you can see, we decorate the class with @injectable as this class may be injected into another class.<\/p>\n<p>Here&#8217;s our WebsocketService.ts<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport &quot;reflect-metadata&quot;;\r\nimport Service from &quot;.\/Service&quot;;\r\nimport { injectable } from &quot;inversify&quot;;\r\n\r\n@injectable()\r\nclass WebsocketService implements Service {\r\n  call(data: string): void {\r\n    console.log(&quot;WebsocketService called&quot;);\r\n  }\r\n}\r\n\r\nexport default WebsocketService;\r\n<\/pre>\n<p>Within the types.ts (below) we create the symbols (keys\/identifiers) for use with our types.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nconst Types = {\r\n  Service: Symbol.for(&quot;Service&quot;),\r\n  Application: Symbol.for(&quot;Application&quot;)\r\n};\r\n\r\nexport default Types;\r\n<\/pre>\n<p>Here&#8217;s an Application interface Application.ts<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ninterface Application {   \r\n  run(): void;\r\n}\r\n\r\nexport default Application;\r\n<\/pre>\n<p>MyApplication.ts<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport &quot;reflect-metadata&quot;;\r\nimport { inject, injectable } from &quot;inversify&quot;;\r\nimport Application from &quot;.\/Application&quot;;\r\nimport Types from &quot;.\/types&quot;;\r\nimport Service from &quot;.\/Service&quot;;\r\n\r\n@injectable()\r\nclass MyApplication implements Application {\r\n  private readonly service: Service;\r\n\r\n  constructor(@inject(Types.Service) service) {\r\n    this.service = service;\r\n  }\r\n\r\n  run(): void {        \r\n    this.service.call(&quot;&quot;);\r\n  }\r\n}\r\n\r\nexport default MyApplication; \r\n<\/pre>\n<p>In the above you can see we&#8217;re injecting (via the @inject decorator on the constructor) a type of symbol type <em>Service<\/em>. Hence this is where the server implementation will be injected into.<\/p>\n<p>To supply inversify with the implementations for various types, we create the file <em>inversify.config.ts<\/em>. In the example file below we bind the symbol type\/identifier with an implementation. <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport { Container } from &quot;inversify&quot;;\r\nimport Service from &quot;.\/Service&quot;;\r\nimport RestService from &quot;.\/RestService&quot;;\r\nimport Types from &quot;.\/types&quot;;\r\nimport WebsocketService from &quot;.\/WebsocketService&quot;;\r\nimport Application from &quot;.\/Application&quot;;\r\nimport MyApplication from &quot;.\/MyApplication&quot;;\r\n\r\nconst container = new Container();\r\n\r\n\/\/container.bind&lt;Service&gt;(Types.Service).to(RestService);\r\ncontainer.bind&lt;Service&gt;(Types.Service).to(WebsocketService);\r\ncontainer.bind&lt;Application&gt;(Types.Application).to(MyApplication);\r\n\r\nexport default container;\r\n<\/pre>\n<p>Finally, here&#8217;s an example implementation of the index.ts<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport container from &quot;.\/inversify.config&quot;;\r\nimport Application from &quot;.\/Application&quot;;\r\nimport Types from &quot;.\/types&quot;;\r\n\r\nconst application = container.get&lt;Application&gt;(Types.Application);\r\napplication.run();\r\n<\/pre>\n<p>There&#8217;s more to inversify than just the code listed above, such as you can have multiple Service implementations and use named bindings to receive the one you want and more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to use an IoC pattern\/library in a project I was working on (a node server application where I would slot in the specific implementations of the data and services at runtime). I cam across inversify, there may be other IoC&#8217;s for TypeScript, but this is the one I looked into and worked a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[270,219,46],"tags":[],"class_list":["post-7516","post","type-post","status-publish","format-standard","hentry","category-inversify","category-ioc-2","category-typescript"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7516","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=7516"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7516\/revisions"}],"predecessor-version":[{"id":7597,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/7516\/revisions\/7597"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=7516"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=7516"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=7516"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}