— type & vs interface extends の速度差を可視化する —
投稿日: 2025年10月22日
🧠 TypeScript 型定義パフォーマンス検証
type & vs interface extends の速度差を可視化する —TypeScript の大型コードベースで、コンパイル時間が妙に長い… と感じたことはありませんか?
実はそれ、type の交差型(&)が原因かもしれません。
この記事では、React の Props を例にtype と interface の**型チェック時間(Check time)**を比較した検証デモを紹介します。
TypeScript では型を合成する方法が複数ありますが、
よく使われるのが次の2つです:
// ① type + &
type A = { name: string }
type B = { age: number }
type C = A & B
// ② interface + extends
interface A { name: string }
interface B extends A { age: number }
一見同じように見えますが、内部処理が大きく異なり、
パフォーマンス(型解析時間)に数倍の差が出ます。
Node.js 24.x(v18 以上なら可)
TypeScript 5.6
計測コマンド:
tsc --extendedDiagnostics
/usr/bin/time -lp(実時間・メモリ使用量の確認)
# 400件の型ブロックを生成(デフォルト)
npx ts-node scripts/generate.ts
# 1000件に増やす
npx ts-node scripts/generate.ts 1000
# interface 版・type 版が src/ 以下に生成されます
生成スクリプトでは、type では交差型 &、interface では継承 extends を再帰的に合成していきます。
npm run bench:type
npm run bench:iface
出力結果に表示される Check time が型解析にかかった純粋な時間です。
実行例(N=3000)
➡️ 約3倍の速度差が出ています。
(type の方が非線形に遅くなる)
/usr/bin/time -lp npm run bench:type
/usr/bin/time -lp npm run bench:iface
real(実行時間)や maximum resident set size(最大常駐メモリ)を比較します。
type(交差型):
即時評価(Eager Evaluation)
& のたびに再帰的に展開 → 構造爆発
キャッシュが効きにくい
interface(継承):
遅延評価(Lazy Evaluation)
「名前付き参照」でキャッシュが効く
スケールしても安定
type & の場合 → 補完やホバー時に数秒ラグが発生することも
interface の場合 → 遅延展開されるため即応答
実務では補完レスポンスの速さが大きく変わるため、
開発体験 (DX) の観点でもinterfaceが圧倒的に有利です。
{
"rules": {
"@typescript-eslint/consistent-type-definitions": ["error", "interface"]
}
}
type Simplify<T> = { [K in keyof T]: T[K] }
便利ですが、大量の型を一気に展開すると逆効果です。
局所的(最終出力段階)でのみ使用しましょう。
Warning: Module type of file is not specified...
→ package.json に "type": "module" を追加すれば解消できます。
動作自体には影響ありません。
🧠 結論
React などの Props 型は、interfaceベースで統一するのが最適解。
🧩 検証コード・スクリプト一式はこちらで公開しています:
👉 https://github.com/Kazuya-Sakashita/ts-perf-demo
# クローンして実行
git clone https://github.com/Kazuya-Sakashita/ts-perf-demo.git
cd ts-perf-demo
npm i
npx ts-node scripts/generate.ts
npm run bench:type
npm run bench:iface