TypeScript: MapをEnumよりも優先すべき理由

利用可能な言語 :

TypeScriptで固定値のセットを表現する際、enumは自然な選択肢に見えるかもしれません。しかし、コードの保守性とパフォーマンスに影響を与える重要な制限があります。Mapがより良い選択肢である理由を見ていきましょう。

Enumの問題点

複雑なアプリケーション開発において、Enumには以下の主要な欠点があります:

  1. 硬直性: 動的な変更が不可能
  2. パフォーマンス: 冗長なJavaScriptコードを生成
  3. 複雑な型付け: イントロスペクションと型の合成が困難
  4. バンドルサイズ: 最終的なコードサイズへの影響

例を見てみましょう:

typescript
1// TypeScriptコード
2enum Status {
3 Active = 'ACTIVE',
4 Inactive = 'INACTIVE',
5}
6
7// トランスパイルされたJavaScriptコード
8var Status = {
9 Active: 'ACTIVE',
10 Inactive: 'INACTIVE',
11 ACTIVE: 'Active',
12 INACTIVE: 'Inactive',
13};
14(function (Status) {
15 Status['Active'] = 'ACTIVE';
16 Status['Inactive'] = 'INACTIVE';
17})(Status || (Status = {}));

このトランスパイルされたコードは以下を生成します:

  • ミラープロパティ(キー ↔ 値)を持つオブジェクト
  • 不要なIIFE(即時実行関数式)
  • 各値の二重参照
  • パフォーマンスに影響を与える追加コード

Mapによる解決策

MapとTypeScriptオブジェクトは、より洗練された柔軟なアプローチを提供します:

typescript
1// constと型による解決策
2const Status = {
3 Active: 'ACTIVE',
4 Inactive: 'INACTIVE',
5} as const;
6
7// 自動的に推論される型
8type Status = (typeof Status)[keyof typeof Status];
9
10// シンプルで効率的なトランスパイル結果
11const Status = {
12 Active: 'ACTIVE',
13 Inactive: 'INACTIVE',
14};

Mapの利点

  1. 型安全性
typescript
1function processStatus(status: Status) {
2 // 無効なステータスでコンパイルエラー
3 console.log(status);
4}
5
6// ランタイム検証
7const isValidStatus = (status: string): status is Status =>
8 Object.values(Status).includes(status as Status);
  1. 拡張性
typescript
1// 動的な追加が可能
2const ExtendedStatus = {
3 ...Status,
4 Pending: 'PENDING' as const,
5};
  1. 高度なパターン
typescript
1// 関連設定
2const StatusConfig = {
3 [Status.Active]: {
4 color: 'green',
5 label: '有効',
6 icon: 'check',
7 },
8 [Status.Inactive]: {
9 color: 'red',
10 label: '無効',
11 icon: 'cross',
12 },
13} as const;
14
15// ユーティリティ型
16type StatusConfig = {
17 [K in Status]: {
18 color: string;
19 label: string;
20 icon: string;
21 };
22};
23
24// 型付きヘルパー関数
25function getStatusConfig(status: Status) {
26 return StatusConfig[status];
27}

実践的なユースケース

1. APIエンドポイント

typescript
1const ApiEndpoints = {
2 Users: '/api/users',
3 Products: '/api/products',
4 Orders: '/api/orders',
5} as const;
6
7type Endpoint = (typeof ApiEndpoints)[keyof typeof ApiEndpoints];
8
9// 自動的なURL型付け
10function fetchData(endpoint: Endpoint) {
11 return fetch(endpoint);
12}

2. 状態管理

typescript
1const LoadingState = {
2 Idle: 'IDLE',
3 Loading: 'LOADING',
4 Success: 'SUCCESS',
5 Error: 'ERROR',
6} as const;
7
8type LoadingState = typeof LoadingState[keyof typeof LoadingState];
9
10function handleState(state: LoadingState) {
11 switch (state) {
12 case LoadingState.Loading:
13 return <Spinner />;
14 case LoadingState.Error:
15 return <ErrorMessage />;
16 // TypeScriptが網羅性をチェック
17 }
18}

詳細な比較表

EnumとMapの詳細な比較:

型安全性

  • Enum: 基本的 (✓)
  • Map: 型推論付きの高度な安全性 (✓✓)

ランタイムパフォーマンス

  • Enum: 低い (✗)
  • Map: 高い (✓)

バンドルサイズ

  • Enum: 大きい (✗)
  • Map: 小さい (✓)

拡張性

  • Enum: 拡張が困難 (✗)
  • Map: 容易に拡張可能 (✓)

イントロスペクション

  • Enum: 制限された機能
  • Map: 完全な機能

TypeScript strict互換性

  • Enum: 互換性あり (✓)
  • Map: より多くの機能で完全互換 (✓✓)

保守性

  • Enum: 保守が複雑
  • Map: 保守が容易

ベストプラクティス

  1. 明示的な命名
typescript
1// 推奨
2const HttpStatus = {
3 Ok: 200,
4 NotFound: 404,
5 ServerError: 500,
6} as const;
7
8// 避けるべき
9const Status = {
10 a: 200,
11 b: 404,
12 c: 500,
13} as const;
  1. Union型
typescript
1// 型安全なユニオンの作成
2type HttpSuccessStatus = 200 | 201 | 204;
3type HttpErrorStatus = 400 | 401 | 404 | 500;
4type HttpStatus = HttpSuccessStatus | HttpErrorStatus;
  1. ランタイム検証
typescript
1function isHttpSuccess(status: number): status is HttpSuccessStatus {
2 return [200, 201, 204].includes(status);
3}

結論

Mapはenumに比べて以下の点で優れた選択肢を提供します:

  • より正確で柔軟な型付け
  • より良いランタイムパフォーマンス
  • 簡素化された保守
  • JavaScriptエコシステムとの優れた互換性

これらの概念をさらに深く理解するには:

あなたの経験を共有して、この記事に貢献してください!

この記事を共有する


Sébastien Timoner

Sébastien TIMONER

リードデベロッパー
カスタム開発エキスパート
Aix-en-Provence, France

Web開発とチームマネジメントのエキスパートとして、高性能なデジタルソリューションの作成と最適化を専門としています。React.js、Node.js、TypeScript、Symfony、そしてIoT向けのZephyr OSなどの最新技術における豊富な専門知識を活かし、offroadLabsにて様々な業界の企業向けに、設計から本番環境までの複雑なSaaSおよびIoTプロジェクトの成功を確実にします。

offroadLabsでは、技術的専門知識と協力的なアプローチを組み合わせたカスタム開発サービスを提供しています。革新的なSaaSソリューションの作成、Zephyr OSを使用したIoTシステムの開発、既存アプリケーションの近代化、またはチームのスキルアップ支援など、各プロジェクトの特定のニーズに合わせた堅牢で高性能なソリューションの提供に取り組んでいます。

エクサンプロヴァンス地域またはフルリモートでのプロジェクトに対応可能です。

TypeScript: MapをEnumよりも優先すべき理由