DI(Dependency Injection) in TypeScript

2019-10-03

You can use “dependency injection" with inversify.

https://github.com/inversify/InversifyJS

Install

npm install inversify reflect-metadata --save

Then you need to set up the following for using Decorators.

{
    "compilerOptions": {
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
    }
}

Abstract class in TypeScript

You should use abstraction class. The most popular way to abstract class is “Interface", but “Abstract class" is used in TypeScript.

import 'reflect-metadata';
import {injectable, inject} from 'inversify';

@injectable()
export default abstract class BaseHoge {
	abstract test(): string
}

@injectable()
export default class Hoge extends BaseHoge {
    constructor(private fuga: BaseFuga) {
        super()
    }

    test(): string {
    	return this.fuga.getTest()
    }
}

@injectable()
export default abstract class BaseFuga {
	abstract getTest(): string
}

@injectable()
export default class Fuga extends BaseFuga {
    getTest(): string {
    	return 'test'
    }
}

Create the DI Container

You inject with DI container.

import 'reflect-metadata';
import { Container, injectable, inject } from "inversify";

import BaseHoge from "./BaseHoge";
import BaseFuga from "./BaseFuga";
import Hoge from "./Hoge";
import Fuga from "./Fuga";

export default class Kernel {

    container: Container

    constructor() {
        this.declareDependencies();
    }

    declareDependencies (): void {
        this.container = new Container();
        this.container.bind(BaseHoge).to(Hoge);
        this.container.bind(BaseFuga).to(Fuga);
    }

    get(serviceIdentifier): T {
        return this.container.get(serviceIdentifier)
    }
}

How to call DI Container. it should DI Kernel class?

const hoge: BaseHoge = new Kernel().get(BaseHoge);