TypeScriptの関数でDIパターン
2020年5月14日
TypeScript

Node.js+TypeScriptでバックエンドを書いてると、DIパターンを使いたい場面が結構ある。

いわゆるDIと言うとコンストラクタインジェクションなどクラスありきの方法が思い浮かぶけれども、実際には関数でもDIパターンを書くことができる。単純に関数のパラメータに依存を受け取ればよい。

// 依存を表現する型
interface Deps {
  appService: AppServiceInterface;
}
    
// DIパターンを記述する関数
function DoSomething({appService}: Deps, params: any) {
  ...
} 

依存を注入する場合には、引数を部分適用するbind()メソッドを使う。

// 依存を注入
const doSomething = DoSomething.bind(null, {
  appService: new MyAppService()
});
    
// 関数を呼び出す
doSomething({
  ...
});

bind()で引数を部分適用すると、引数の数が変わってしまうので、それが嫌な場合には、次のコードのようにthisで依存を受け取るのもいいだろう。

// thisで依存を表現する
function DoSomething(this: Deps, params: any) {
   ...
}
    
// 依存を注入する
const doSomething = DoSomething.bind({
  appService: new MyAppService()
});

自分がTypeScriptを書く場合には、あんまりクラスを書かないので、こういった関数でDIパターンが書けると助かるケースが結構ある。そういった時には依存を単に引数で受け取る関数を書けば良い。依存を注入するには、引数を固定するbind()で依存を渡しておく。

この書き方の課題としては、こういった関数でのDIパターンに対応したDIコンテナのライブラリは今の所ないので、自分でそういったライブラリを作ったり、Factoryパターンで依存を注入したりする必要があるだろう。


久保田光則 (id:anatoo)

福岡在住のソフトウェアエンジニア・UI/UXデザイナー。RelayHub, LLCという会社をやっています。 技術評論社 『HTML5 ハイブリッドアプリ開発[実践]入門』 『Webフロントエンド ハイパフォーマンス チューニング』 好評発売中。

  
© Mitsunori Kubota