Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency injection in TypeScript

I'm looking into the possibilities to do TDD with TypeScript. If I write my tests in TypeScript, is it possible to make the import statements return mocks for my class under test? Or is the only feasible approach to write the tests in pure javascript and deal with injecting AMDs myself?

like image 541
Sop Killen Avatar asked Apr 17 '13 20:04

Sop Killen


People also ask

What is dependency injection in TypeScript?

Dependency injection (DI): a variant of IoC in which objects receive other objects as dependencies instead of constructors or setters. Decorators: functions that enable composition and are wrappable around classes, functions, methods, accessors, properties, and parameters.

Does TypeScript support dependency injection?

The D letter in SOLID is the Dependency Inversion principle. It helps to decouple modules from each other so that you can easily swap one part of the code for another. One of the techniques that helps to follow this principle is Dependency Injection.

What is the use of dependency injection in Angular?

Dependency injection, or DI, is one of the fundamental concepts in Angular. DI is wired into the Angular framework and allows classes with Angular decorators, such as Components, Directives, Pipes, and Injectables, to configure dependencies that they need.


1 Answers

I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.

You need to follow 3 basic steps to use it:

1. Add annotations

The annotation API is based on Angular 2.0:

import { injectable, inject } from "inversify";  @injectable() class Katana implements IKatana {     public hit() {         return "cut!";     } }  @injectable() class Shuriken implements IShuriken {     public throw() {         return "hit!";     } }  @injectable() class Ninja implements INinja {      private _katana: IKatana;     private _shuriken: IShuriken;      public constructor(         @inject("IKatana") katana: IKatana,         @inject("IShuriken") shuriken: IShuriken     ) {         this._katana = katana;         this._shuriken = shuriken;     }      public fight() { return this._katana.hit(); };     public sneak() { return this._shuriken.throw(); };  } 

2. Declare bindings

The binding API is based on Ninject:

import { Kernel } from "inversify";  import { Ninja } from "./entities/ninja"; import { Katana } from "./entities/katana"; import { Shuriken} from "./entities/shuriken";  var kernel = new Kernel(); kernel.bind<INinja>("INinja").to(Ninja); kernel.bind<IKatana>("IKatana").to(Katana); kernel.bind<IShuriken>("IShuriken").to(Shuriken);  export default kernel; 

3. Resolve dependencies

The resolution API is based on Ninject:

import kernel = from "./inversify.config";  var ninja = kernel.get<INinja>("INinja");  expect(ninja.fight()).eql("cut!"); // true expect(ninja.sneak()).eql("hit!"); // true 

The latest release (2.0.0) supports many use cases:

  • Kernel modules
  • Kernel middleware
  • Use classes, string literals or Symbols as dependency identifiers
  • Injection of constant values
  • Injection of class constructors
  • Injection of factories
  • Auto factory
  • Injection of providers (async factory)
  • Activation handlers (used to inject proxies)
  • Multi injections
  • Tagged bindings
  • Custom tag decorators
  • Named bindings
  • Contextual bindings
  • Friendly exceptions (e.g. Circular dependencies)

You can learn more about it at https://github.com/inversify/InversifyJS

like image 190
Remo H. Jansen Avatar answered Oct 05 '22 14:10

Remo H. Jansen