- NodeでもTypeScript で書きたい
- DI欲しくなる
- シングルトンなサービスを使いたい
- new したくない
- テストしやすい
リポジトリ: https://github.com/cyokodog/inversifyjs_study
InversifyJS
- inversify/InversifyJS: A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
- Angular と同じように class-based なDIができる
- 昨日ちょっと使ってみた
準備
npm install inversify reflect-metadata --save
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["es6"],
"types": ["reflect-metadata"],
"module": "commonjs",
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
サンプル
service.ts
import { injectable } from "inversify";
@injectable()
export class Katana {
sound = "ブンッ!";
swing() {
return this.sound;
}
}
@injectable()
export class Samurai {
constructor(private katana: Katana) {}
fight() {
return this.katana.swing();
}
pwoerUp() {
this.katana.sound = "ブウウウウンッ!!";
}
}
inversify.config.ts
import { Container } from "inversify";
import { Samurai, Katana } from "./services";
const rootContainer = new Container();
rootContainer.bind(Katana).toSelf();
rootContainer.bind(Samurai).toSelf();
export const container = rootContainer.createChild();
実行!
import "reflect-metadata";
import { container } from "./inversify.config";
import { Samurai } from "./services";
const samurai = container.get(Samurai);
console.log(samurai.fight()); // ブンッ!
samurai.pwoerUp();
console.log(samurai.fight()); // ブウウウウンッ!!
シングルトンになってるかな?
const samuraiA = container.get(Samurai);
const samuraiB = container.get(Samurai);
samuraiA.pwoerUp();
console.log(samuraiA.fight()); // ブウウウウンッ!!
console.log(samuraiB.fight()); // ブンッ!
なってない....!
inSingletonScope()
シングルトンにするには bind() する際に、 inSingletonScope() する必要がある
rootContainer.bind(Samurai).toSelf().inSingletonScope();
const samuraiA = container.get(Samurai);
const samuraiB = container.get(Samurai);
samuraiA.pwoerUp();
console.log(samuraiA.fight()); // ブウウウウンッ!!
console.log(samuraiB.fight()); // ブウウウウンッ!!
モックで差し替えてみる
@injectable()
export class KatanaMock implements Katana {
sound = "スカッ!";
swing() {
return this.sound + "(mock)";
}
}
container.bind(Katana).to(KatanaMock);
const samuraiA = container.get(Samurai);
const samuraiB = container.get(Samurai);
console.log(samuraiA.fight()); // スカッ!(mock)
samuraiA.pwoerUp();
console.log(samuraiB.fight()); // ブウウウウンッ!!(mock)
良さそう、使ってみる!