巨大なInterfaceに怯えるな:構造的部分型をハックする「最小限Mocking」戦略
TypeScriptの最大の武器であり、同時に初心者が最も躓く壁、それが「構造的部分型(Structural Subtyping)」だ。
多くのエンジニアが「Interfaceは型定義の契約書である」と習う。しかし、プロダクション環境の肥大化したInterfaceを前に、「この50個のプロパティを持つオブジェクトをモックするために、全プロパティを埋めなければならないのか?」と絶望したことはないだろうか。
結論から言えば、その必要はない。 TypeScriptの型システムを深く理解すれば、必要な部分だけを切り出し、型安全を維持したまま最小限のモックを注入する、極めて洗練された設計が可能になる。
—
1. なぜ「全実装」がアンチパターンなのか
巨大なInterface(例えば、APIレスポンスの巨大な型定義など)をすべて実装したモックを作ると、以下のような負の連鎖が始まる。
- 変更の伝播: Interfaceに1つプロパティが追加されるたびに、無関係なテストまで壊れる。
- 認知負荷: テストの本質ではない「ダミーデータ」にコードの8割が占有される。
- 保守性の低下: テストデータがDRY(Don’t Repeat Yourself)に反し、修正が困難になる。
TypeScriptが「構造的」であるということは、「要求されたプロパティさえあれば、他が欠けていても(あるいは余計でも)それは型として合致する」という性質を意味する。これを利用しない手はない。
—
2. 「部分型抽出」によるMocking戦略
実務で私が推奨するのは、`Pick`や`Partial`を駆使したユーティリティ型による「モック用インターフェースの抽出」だ。
実践:巨大API型からの「必要な部分だけ」の抽出
例えば、複雑な`User`型があるとする。
// 本番コードにある巨大なInterface
interface User {
id: string;
name: string;
email: string;
preferences: { theme: ‘dark’ | ‘light’; notifications: boolean };
// …その他30個のプロパティ
}
/
- 解決策: テスト専用の「部分型」を定義する
- 必要なプロパティだけをPickし、さらに必要に応じてPartialで任意化する
/
type UserMock = Pick
const createMockUser = (overrides?: Partial
return {
id: ‘test-id’,
name: ‘Test User’,
// 他の必須プロパティはデフォルト値で埋める
email: ‘test@example.com’,
preferences: { theme: ‘light’, notifications: true },
…overrides,
} as User; // ここで型キャストを行うのがポイント
};
なぜこの手法が「堅牢」なのか
- `as User` を使っているが、これは単なるキャストではなく、`createMockUser`が返すオブジェクトが`User`の構造を必要最小限満たしていることを保証している。
- 万が一、`User`側で必須プロパティが変更された場合、`createMockUser`内の初期値設定でコンパイルエラーが出るため、型安全性は担保される。
—
3. パフォーマンスとコンパイラAPIの知見
ここで重要なのは、「型定義の複雑化」と「コンパイル速度」のトレードオフだ。
`Pick`や`Omit`を多用しすぎると、TypeScriptの型評価器(Checker)は複雑な再帰的計算を行うことになる。モックのための型変換をやりすぎると、ビルド時間が肥大化する。
- 教訓: モックのための型定義は「再利用可能なユーティリティ」として一箇所にまとめ、計算コストを最小化せよ。
- インラインで書かない: `createMockUser` のようなファクトリ関数を挟むことで、コンパイラが一度推論した結果をキャッシュしやすくなり、エディタの補完(IntelliSense)も高速に維持できる。
—
4. まとめ:コードは「契約」であり「柔軟な実体」である
TypeScriptの型システムは、静的な檻ではない。構造的部分型は、私たちが「今、この瞬間に必要なデータ」にだけ集中するための柔軟な道具だ。
1. Interfaceをそのままモックにするな: `Pick`を使って「テストに必要な最小限の型」を定義せよ。
2. ファクトリ関数を介在させよ: `as User` との合わせ技で、型安全なモック生成ハブを作れ。
3. 変更に強いテストを書け: テストコードが壊れる時は、「仕様が変わった時」だけでいい。「ダミーデータが足りなくなった時」に壊れるテストは、設計を見直すべきサインだ。
コードレビューでこの設計方針を共有すれば、チームのテストコードは劇的にスリムになり、あなたのプロダクトはより速く、より安全にリリースされるようになるだろう。
型を恐れるな。型を掌握し、デザインしろ。