こんにちは。TypeScriptという深淵な海へようこそ。
現場でバリバリと型を書いていくうちに、「あれ? `interface` で継承するのと `type` で交差型(`&`)を作るのって、結局何が違うんだろう?」という疑問にぶつかることはありませんか?
どちらも「複数の型を合成する」という目的は同じですが、TypeScriptのコンパイラ(TSC)から見ると、その挙動は全くの別物です。今日は、コードの裏側でコンパイラが何をしているのか、そしてなぜ大規模開発において「使い分け」が重要なのかを、伝説的な知見を交えて解説していきますね。
ここをクリアすれば、型システムの構造を一段上の視座で理解できるようになりますよ。
—
1. 基本の「型」と「継承」の顔ぶれ
まずは基本のおさらいです。
Interfaceの継承(extends)
オブジェクトの「設計図」を拡張するイメージですね。
interface Animal {
name: string;
}
// Animalを継承して新しい設計図を作る
interface Dog extends Animal {
bark(): void;
}
型エイリアスの交差型(Intersection Types: &)
複数の型を「物理的に結合」して、新しい型を作り出すイメージです。
type Animal = { name: string };
type Pet = { owner: string };
// 2つの型を合体させる
type Dog = Animal & Pet;
一見すると、どちらも「名前とオーナーを持つ型」になりますよね。ですが、コンパイラの脳内では全く異なる処理が行われています。
—
2. コンパイラは「どう」見ているのか?
ここが本質です。TypeScriptのコンパイラは、型を解決する際に「遅延評価(Lazy Evaluation)」という戦略をとります。
Interface継承の優位性:キャッシュと最適化
`interface` は、コンパイラにとって「名前付きの構造体」として扱われます。継承関係がある場合、コンパイラは単に「親の定義をコピーして追加する」というマッピングを行います。
もしプロパティが重複しても、インターフェースは「あ、これ親にあるやつだね」と、エラーチェックをスキップしたり、型定義をキャッシュしたりしやすい構造をしています。IDE(VS Codeなど)でホバーしたときに、すっきりと展開された型が表示されるのは、この最適化のおかげです。
交差型(&)の代償:再帰的な計算
一方で、`&` は「これとこれを混ぜろ」という命令です。コンパイラは、その型が使われるたびに、内部的に「AとBをマージした結果、プロパティはどうなる?」という計算を都度実行します。
特に大規模なプロジェクトで、複雑な型同士を `&` で連結し続けるとどうなるでしょうか?
コンパイラは「型A と 型B と 型C と…」という無限のパズルを解き続けることになり、型チェックの計算量が指数関数的に増大します。これが「ビルドが遅い」と感じる原因の一つです。
—
3. どっちを使えばいいの?判断基準
現場のリーダーとして、皆さんに推奨するルールはこれです。
1. 「オブジェクトの定義」なら `interface` を優先する
- 拡張性があり、コンパイラにとって親切(キャッシュが効く)。
- エラーメッセージが圧倒的に読みやすい。
2. 「複数の型を一時的に組み合わせる」なら `type` & を使う
- 関数引数や、複雑なユーティリティ型を作る際は `type` の方が柔軟です。
- 継承できない「プリミティブ型」や「リテラル型」を混ぜたいときは、`type` 一択になります。
陥りやすい罠:プロパティの衝突
もし同じプロパティ名で型が違うものを `&` で結合しようとすると、コンパイラは `never`(そんな型は存在し得ない)を返します。
type A = { id: string };
type B = { id: number };
type ErrorType = A & B;
// id: string & number つまり id: never になります。
`interface` の継承なら、継承時に「型が合っていません」とコンパイルエラーを出して教えてくれます。この「早期発見」のしやすさも、`interface` が大規模開発で好まれる理由です。
—
まとめ:TypeScriptを掌握するために
- Interface継承:コンパイラにとって「優しい」。ビルド時間が安定し、型情報が整理されやすい。
- 交差型(&):コンパイラにとって「負荷が高い」。計算コストがかかるため、必要な場所でのみ使う。
「なんとなく便利だから」で `type` を乱用するのではなく、「これは設計図なのか? それとも計算の結果なのか?」を意識してみてください。
型システムは、ただのコードチェックツールではありません。コンパイラとの対話です。この対話の密度を高めていけば、皆さんの書くコードはより堅牢で、かつビルドの速い素晴らしいものになります。
ここをマスターすれば、もうTypeScriptの型定義で迷うことはありませんよ。さあ、自信を持ってコードを書いていきましょう!