TypeScriptでDI(Dependency Injection)-依存性の注入

2019-09-23

TypeScriptでDI(Dependency Injection)するならinversify

https://github.com/inversify/InversifyJS

インストール

npm install inversify reflect-metadata --save

Decoratorを使用するのでtsconfig.jsonに以下の設定を追加。

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

abstractクラスで抽象化

クラスの抽象化を作成する。通常interfaceクラスで抽象化を定義するが、TypeScriptの場合はabstractクラスで抽象化する。

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'
    }
}

DIコンテナ作成

DIコンテナを作成し注入して、利用する。

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)
    }
}

呼び出し。KernelクラスもDIするべきか。。また、nodejsの根元からDIした方が本当は美しいのか。

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