Skip to content

InferDI を選ぶ理由

手動のコンストラクター注入は堅実な出発点です。依存が見え、TypeScript は個々の new 呼び出しを検査できます。グラフが数行の組み立てを超え、ライフタイム、スコープ、非同期の準備状態、モジュール、破棄も扱う段階で InferDI が役立ちます。

構成を一つのグラフとして検査する

各登録は新しいコンテナー型を返します。その型には既知のキー、サービス型、ライフタイム、非同期状態、不足しているスコープ入力が記録されます。後続の登録は、未知のキー、不適合なコンストラクター引数、重複キー、短いライフタイムを保持するシングルトンを受け付けません。

ts
import { 
Container
} from '@inferdi/inferdi'
class
Database
{
find
(
id
: string) {
return {
id
}
} } class
UserService
{
constructor(readonly
database
:
Database
) {}
} const
app
= new
Container
()
.
registerClass
('database',
Database
, [])
.
registerClass
('users',
UserService
, ['database'])
const
users
=
app
.
get
('users')
const users: UserService

この累積状態を指して、InferDI は「グラフが型になる」と説明しています。構成を複数ファイルへ分けても、モジュールが同じ要件を保ちます。

手動配線に加わるもの

手動の new UserService(database) も引数を検査します。ただし、登録のライフタイム、依存による非同期状態の伝播、再利用モジュールの要件、スコープが所有するキャッシュ資源までは追跡しません。InferDI は選択を明示したまま、グラフ全体の契約とライフサイクル管理を追加します。

組み立てコードは残ります。レビューする人は、選んだ実装と依存の順序をその場で確認できます。

実際の仕事をする小さなランタイム

コアの実行時依存はゼロです。デコレーター、metadata reflection、Proxy ベースの解決も使いません。本番バンドルには gzip 3 KiB 未満という強制予算があります。キャッシュヒットは 1 回の Map.get() から始まり、明示的な undefined は内部マーカーで表現されます。

型はコンパイル後に消えますが、コンテナーは登録、オブジェクト生成、キャッシュ、実行時診断、所有資源の破棄を行います。デフォルトモードは循環とライフタイムの診断を保持します。{ fast: true } は一部の検査を省く、固定グラフ向けの別契約です。

ビジネスロジックは通常のコードのまま

ドメインサービスが受け取るのは通常のコンストラクター引数や関数引数です。InferDI の import も resolver も必要ありません。コンテナーは構成ルートとライフサイクル境界に置き、そこで実装を選びスコープを開きます。

単体テストでは偽の依存を渡してサービスを直接作れます。InferDI を交換するなら登録とフレームワーク接続は書き換える必要がありますが、境界を守っていれば業務ルールはそのままです。構成ルートでファイル分割を確認できます。

明示的なスコープと所有権

スコープは HTTP リクエスト、ジョブ、テナント操作など、境界を持つ作業単位を表せます。コンテナーは自分が所有してキャッシュしたクラスとファクトリーの結果を破棄します。値、オーバーライド、スコープ入力、トランジェント結果は呼び出し側の所有です。親子コンテナーが互いを自動破棄することはありません。

アダプターはコアへフレームワーク固有の意味を加えずに、この規則を React、Fastify、Hono、Koa、Express、Elysia のライフサイクルへ接続します。

保証の境界

TypeScript は構造的型付けです。同じ形の値はブランド型を使わない限り交換可能で、any やキャストは検査を回避できます。広い実行時キーはグラフの精度を下げます。await 後の動的な依存読み取りは、同期呼び出しスタックによる循環追跡に参加できません。

InferDI はアーキテクチャを発見せず、循環を修復せず、すべてのリークを防がず、あらゆるアプリケーションを高速化するものでもありません。宣言した関係を検査し、実行時機構を小さく保ちます。次はクイックスタートか、実際の診断を載せた型安全性へ進んでください。