InversifyJS の bind にコンストラクタを使うと型情報を推論できる
InversifyJS を使ってクラスを bind する時、Symbol や string を使うことができるが同様にクラスのコンストラクタを利用できる。TypeScriptを利用しているときにコンストラクタを使った bind を使うと、識別に使用したコンストラクタを持つクラスを型情報として推論できる。更に、コンストラクタでバインドした場合、@inject デコレータの設定を省略できるので記載量も減るというメリットが有る。 シンボルを利用した例
通常用途でよく見る形。Symbol や string で container.bind で登録すると container.get したときの型が unknown (バージョンによっては any) になるのでジェネリクスの型指定で Hoge を明示する必要がある。この指定をコピペで間違うと実行時に手痛い目を見ることになる。
code:ts
// 環境に応じて bind 先を変更する
const dev = process.env.NODE_ENV !== 'production'
// 各種実装を用意
class Hoge { ... }
class HogeFake implements Hoge { ... }
// 識別用のシンボルを用意
const symbols = {
hoge: Symbol.for('hoge'),
}
// コンテナを作ってシンボルを識別子にしてクラスをバインド
const container = new Container()
container.bind(symbols.hoge).to(dev ? HogeFake : Hoge)
// 使うときは container.get を使用する (型は unknown もしくは any になる)
const h = container.get<Hoge>(symbols.hoge)
コンストラクタを使った例
今回紹介する例。Symbol や string を使った例と大枠同じだが container.bind と container.get で指定する識別子にクラスそのものを渡しているところがポイント。こうすると container.get したときに識別子に使った Hoge が型として推論されるようになる。型の間違いが起こる余地が減るということになる。
code:ts
// 環境に応じて bind 先を変更する
const dev = process.env.NODE_ENV !== 'production'
// 各種実装を用意
class Hoge { ... }
class HogeFake implements Hoge { ... }
// コンテナを作ってコンストラクタを識別子にしてにクラスをバインド
const container = new Container()
container.bind(Hoge).to(dev ? HogeFake : Hoge)
// 使うときは container.get を使用する (型は Hoge になる)
const h = container.get(Hoge)
※ サンプル中に HogeFake が Hoge を implements するように指定しているが TypeScript ならではのアレ。お好みで調整してください。 @inject の省略
inject の識別子にコンストラクタなどの具象を使った場合、自動でバインドされるので @inject による明示が不要になる。
In case of concrete injections, you can simply define your constructor parameters as usual without using the @inject decorator.