0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScriptにおける交差型と継承のパフォーマンス調査

Last updated at Posted at 2025-10-28

はじめに

この記事はTypeScriptのコンパイルに交差型がどれくらい影響を与えるかを調べてみたものとなります。

きっかけはTypeScript公式のPerformance wikiページを読んだことでした。

Interfaces create a single flat object type that detects property conflicts, which are usually important to resolve! Intersections on the other hand just recursively merge properties, and in some cases produce never. Interfaces also display consistently better, whereas type aliases to intersections can't be displayed in part of other intersections. Type relationships between interfaces are also cached, as opposed to intersection types as a whole. A final noteworthy difference is that when checking against a target intersection type, every constituent is checked before checking against the "effective"/"flattened" type.

For this reason, extending types with interfaces/extends is suggested over creating intersection types.

- type Foo = Bar & Baz & {
-      someProp: string;
- }
+ interface Foo extends Bar, Baz {
+      someProp: string;
+ }

そこには「交差型よりもインターフェースを優先する方が、コンパイルパフォーマンスには良い」という記載があったのですが、具体的な数値の記載が見当たりませんでした。
そこで、「実際にはどの程度ちがうのか?」「キャッシュがどれくらいコンパイルパフォーマンスに効いているのか」という疑問が湧いたため、自分で測定してみることにしました。

測定方法

実際にアプリケーション作成で使うような形ではなく、下記のような実証用コードを用いてコンパイルにかかった時間を測定しました。

公式Wikiにも記載があるとおり、コードベースによってコンパイル速度への影響が変わる可能性があるようです。今回は実証用であることを念頭に置いて、記事を読み進んでいただけると嬉しいです。

例:3個の交差型用実証コード
type Type1 = { 
    prop1_1: string; 
};
type Type2 = { 
    prop2_1: string; 
};
type Type3 = { 
    prop3_1: string; 
};

type CombinedType = Type1 & Type2 & Type3;

function testFunction(obj: CombinedType) {
    const access1 = obj.prop1_1;
    const access2 = obj.prop2_1;
    const access3 = obj.prop3_1;

    return obj;
}
例:3個のinterface継承実証コード
interface Type1 { 
    prop1_1: string; 
};
interface Type2 { 
    prop2_1: string; 
};
interface Type3 { 
    prop3_1: string; 
};

interface CombinedType extends Type1, Type2, Type3 {}

function testFunction(obj: CombinedType) {
    const access1 = obj.prop1_1;
    const access2 = obj.prop2_1;
    const access3 = obj.prop3_1;

    return obj;
}

他筆者が利用したパッケージ群のバージョンも参考までに記載しておきます。

  • TypeScript:5.6.0
  • @types/node:22.7.0
  • Node:20.15.0

比較内容

  1. 交差させる型・継承する型を増やした時の比較
    • 各型のプロパティの数は固定
    • 関数内でアクセスするプロパティの数も固定
  2. 各型のプロパティのみを増やした時の比較
    • 交差させる型・継承する型数は固定
    • 関数内でアクセスするプロパティの数も固定
  3. 関数内でアクセスするプロパティのみを増やした時の比較
    • 交差させる型・継承する型数は固定
    • 各型のプロパティの数は固定

これらをキャッシュあり・なし × type・interfaceの4パターンで、測定対象が、1, 10, 100, 1000, 10000で増加する時の測定をおこないました。いずれも5回測定し、有意差が実際に得られるかも見てみました。

比較結果

交差させる型・継承する型を増やした時を増やした時の結果

image.png

型数 交差型(秒) インターフェース(秒) キャッシュ効果 性能差 統計的評価
キャッシュなし→あり キャッシュなし→あり 改善倍率 Interface/Type 交差型vs Interface差
1 2.05→2.85 (+0.80秒, 1.39倍) 1.97→3.03 (+1.06秒, 1.54倍) Interface有利 なし: 0.96倍, あり: 1.06倍 統計的誤差
10 2.00→2.75 (+0.75秒, 1.37倍) 2.12→2.88 (+0.76秒, 1.36倍) 同程度 なし: 1.06倍, あり: 1.05倍 統計的誤差
100 2.14→2.84 (+0.70秒, 1.33倍) 2.05→2.76 (+0.71秒, 1.35倍) 同程度 なし: 0.96倍, あり: 0.97倍 統計的誤差
1000 2.86→2.80 (-0.06秒, 0.98倍) 2.98→2.72 (-0.26秒, 0.91倍) Interface有利 なし: 1.04倍, あり: 0.97倍 統計的誤差
10000 82.4→12.0 (-70.4秒, 0.15倍) 157.4→3.5 (-153.9秒, 0.02倍) Interface圧勝 なし: 1.91倍, あり: 0.29倍 🔥有意差あり

各型のプロパティのみを増やした時の結果

image.png

プロパティ数 交差型(秒) インターフェース(秒) キャッシュ効果 性能差 統計的評価
キャッシュなし→あり キャッシュなし→あり 改善倍率 Interface/Type 交差型vs Interface差
1 2.59→2.65 (+0.06秒, 1.02倍) 2.36→2.57 (+0.21秒, 1.09倍) 同程度 なし: 0.91倍, あり: 0.97倍 統計的誤差
10 2.19→2.63 (+0.44秒, 1.20倍) 2.47→2.64 (+0.17秒, 1.07倍) 同程度 なし: 1.12倍, あり: 1.00倍 統計的誤差
100 2.48→2.50 (+0.02秒, 1.01倍) 2.50→2.60 (+0.10秒, 1.04倍) 同程度 なし: 1.01倍, あり: 1.04倍 統計的誤差
1000 2.59→2.53 (-0.06秒, 0.98倍) 2.70→2.61 (-0.09秒, 0.97倍) 同程度 なし: 1.04倍, あり: 1.03倍 統計的誤差
10000 3.81→3.13 (-0.68秒, 0.82倍) 4.30→3.42 (-0.88秒, 0.80倍) 同程度 なし: 1.13倍, あり: 1.09倍 統計的誤差

関数内でアクセスするプロパティのみを増やした時の結果

image.png

アクセス数 交差型(秒) インターフェース(秒) キャッシュ効果 性能差 統計的評価
キャッシュなし→あり キャッシュなし→あり 改善倍率 Interface/Type 交差型vs Interface差
1 2.40→2.67 (+0.27秒, 1.11倍) 2.49→2.45 (-0.04秒, 0.98倍) 不安定 なし: 1.04倍, あり: 0.91倍 統計的誤差
10 2.67→2.49 (-0.18秒, 0.93倍) 2.42→2.59 (+0.17秒, 1.07倍) 不安定 なし: 0.91倍, あり: 1.04倍 統計的誤差
100 2.62→2.50 (-0.12秒, 0.95倍) 2.58→2.42 (-0.16秒, 0.94倍) 同程度 なし: 0.98倍, あり: 0.97倍 統計的誤差
1000 2.49→2.43 (-0.06秒, 0.98倍) 2.58→2.50 (-0.08秒, 0.97倍) 同程度 なし: 1.04倍, あり: 1.03倍 統計的誤差
10000 2.59→2.48 (-0.11秒, 0.96倍) 2.54→2.43 (-0.11秒, 0.96倍) 同程度 なし: 0.98倍, あり: 0.98倍 統計的誤差

まとめ

交差型 vs インターフェースで有意差があったケースは、交差させる型・継承する型を増やした時を増やした時型数が10000のケースのみでした。またキャッシュ自体も交差させる型・継承する型を増やした時を増やした時のみで有効である結果が今回は得られました。

また、各グラフの縦軸を見ていただけると分かるかと思いますが、今回の測定項目の中で最もコンパイル速度に影響を与えるのは交差・継承させる型数であることもわかりました。

その他として、今回の測定範囲では、各型のプロパティのみを増やした時における有意差は得られませんでした。しかしながら、グラフの傾向を見るにプロパティ数をより増加させることで、交差型とインターフェースの間に差がでてくるようになる可能性があります。

さいごに

測定方法の欄でも記載した通り、今回の結果は本検証用に作成したコードのコンパイル速度を算出したものであり、実際のアプリケーション作成で使うようなケースを対象に測定したものではありません。
フレームワークやライブラリを利用することでもまた結果が変わる可能性はあるので、それようにして検証を行ってみるもの面白いかもしれません。

参考

TypeScript公式のPerformance wikiページ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?