【実務・中級編】Interfaceの「構造的部分型」を逆手に取ったMocking戦略 – TypeScript コア・型システムの基礎解析バイブル

巨大な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 & Partial>;

const createMockUser = (overrides?: Partial): User => {
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. 変更に強いテストを書け: テストコードが壊れる時は、「仕様が変わった時」だけでいい。「ダミーデータが足りなくなった時」に壊れるテストは、設計を見直すべきサインだ。

コードレビューでこの設計方針を共有すれば、チームのテストコードは劇的にスリムになり、あなたのプロダクトはより速く、より安全にリリースされるようになるだろう。

型を恐れるな。型を掌握し、デザインしろ。

タイトルとURLをコピーしました