Featured image of post TypeScriptにおける新しい標準デコレータ(Decorators)の使い方 Featured image of post TypeScriptにおける新しい標準デコレータ(Decorators)の使い方

TypeScriptにおける新しい標準デコレータ(Decorators)の使い方

長らく実験的な機能だったデコレータがステージ3〜4標準へ移行したことを受け、TypeScript 5.0以降での新しい実装方法とライブラリでの導入事例を紹介します。

はじめに

TypeScriptにおける デコレータ(Decorators) は、AngularやNestJS、TypeORMなどの主要フレームワークで広く使われてきた非常に重要な構文です。

しかし、従来のデコレータは長年にわたり「実験的機能(experimentalDecorators: true)」という位置づけであり、ECMAScript(JavaScript)の標準化プロセスとは乖離した独自仕様で動作していました。

これが、TypeScript 5.0 以降において、ついに ECMAScript標準(Stage 3/4)に準拠した新しいデコレータ が正式にサポートされました。新仕様では、従来の動作や型安全性が大きくアップデートされています。本記事では、新仕様のデコレータの書き方と移行のポイントを解説します。


1. 従来のデコレータと新しい標準デコレータの違い

最大の違いは、「実験的デコレータ(旧仕様)」と「標準デコレータ(新仕様)」の動作アーキテクチャと記述方法です。

構成設定の変更

  • 旧仕様: tsconfig.json 内で "experimentalDecorators": true を有効化する必要がありました。
  • 新仕様: デフォルト(未指定、または false)の状態で動作します。コンパイルターゲットが新しいJavaScript標準に対応していれば、そのままネイティブなデコレータとして解釈されます。

メタデータ操作と引数の厳格化

旧仕様のデコレータはクラスプロパティやメソッドの記述子(Descriptor)を比較的緩く変更できましたが、型安全性が不十分でした。新仕様のデコレータは、関数の引数に context オブジェクト が渡されるようになり、デコレート対象のメタデータ情報(名前、アクセス制御など)に型安全にアクセスできるようになりました。


2. メソッドデコレータの具体的な書き方例

メソッドの実行前後にログを出力する、最もシンプルな「ロギング・デコレータ」を新仕様で書いてみましょう。

デコレータ関数の定義

// 新仕様のメソッドデコレータのシグネチャ
function logMethod<This, Args extends any[], Return>(
  target: (this: This, ...args: Args) => Return,
  context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
  const methodName = String(context.name);

  // 元のメソッドをラップした新しい関数を返却する
  return function (this: This, ...args: Args): Return {
    console.log(`[LOG] ${methodName} が呼び出されました。引数:`, args);
    const result = target.apply(this, args);
    console.log(`[LOG] ${methodName} の処理が終了しました。結果:`, result);
    return result;
  };
}

デコレータの適用

class UserService {
  @logMethod
  getUser(id: number) {
    return { id, name: "Takao" };
  }
}

const service = new UserService();
service.getUser(42); // 実行するとコンソールにログが出力されます
  • ClassMethodDecoratorContext: コンテキストオブジェクトを通じて、対象が private メソッドか、static メソッドか、名前は何か(context.name)といったメタデータを実行前に安全にチェックできます。

3. 実践:移行における注意点と課題

新仕様のデコレータは非常に強力ですが、既存プロジェクトを移行する際にはいくつか注意すべき点があります。

  1. メタデータ(Reflect Metadata)の挙動変更: 従来のデコレータ(Angular等)は reflect-metadata ライブラリに依存し、実行時の型情報(Dependency Injectionなど)をメタデータとして保持していました。新標準のデコレータは独自のメタデータシステムに移行しているため、ライブラリ側のバージョンアップ対応状況を確認する必要があります。
  2. パラメータデコレータ(引数デコレータ)の廃止: 旧仕様でよく見られた、メソッドの引数個別に適用するデコレータ(例: getUser(@Inject() userId: number))は、ECMAScript標準仕様(Stage 3段階)からは除外されました。クラス、メソッド、フィールド、アクセサ、オートアクセサのみがデコレート対象となります。

まとめ

TypeScriptのデコレータは、今回の標準化により「将来的にブラウザでそのまま動作するネイティブ仕様」へと昇華しました。

  1. experimentalDecorators オプションなしで型安全に利用可能になった
  2. context を使ったリッチなメタデータ操作が安全に行える
  3. パラメータデコレータの廃止など、従来の書き方からの移行には注意が必要

新仕様のデコレータを取り入れ、より堅牢で綺麗なメタプログラミングをTypeScriptプロジェクトで実践していきましょう。