0Pricing
Frontend Academy · レッスン

デコレーターとメタデータ

実験的なデコレーターを有効にし、クラス、メソッド、プロパティのデコレーターを記述して、依存性注入のパターンにreflect-metadataを使用します。

「デコレーターとメタデータ」はCoddyKit上の無料Frontend Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはFrontend Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Frontend Academyコースには全4レッスンが含まれています。

デコレーターとは

デコレーターは、クラス、メソッド、プロパティ、パラメータを定義時に変更する関数です。Angular、NestJS、TypeORM、クラスベースのMobXで多用されています。

デコレーターの構文

クラス、メソッド、プロパティ、またはパラメータの前に@DecoratorNameを付けます。デコレーター関数はクラスが定義されたときに実行されます。

@Component({ selector: 'app-root' })
export class AppComponent {
  @Input() title: string;

  @HostListener('click')
  onClick() {
    console.log('clicked');
  }
}

デコレーターを有効にする

tsconfig.jsonでexperimentalフラグを有効にします。新しいECMAScript Stage 3デコレーター(TypeScript 5.0以降)ではこのフラグは不要ですが、動作の意味が異なります。

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

クラスデコレーター

コンストラクターを引数として受け取ります。クラスを置き換えたり、ラップしたり、機能を追加したりできます。

function Singleton<T extends { new (...a: any[]): {} }>(target: T) {
  let instance: T;
  return class extends target {
    constructor(...args: any[]) {
      if (!instance) instance = new target(...args) as T;
      return instance;
    }
  };
}

@Singleton
class Logger { /* ... */ }

メソッドデコレーター

(target、key、descriptor)を受け取ります。メソッドをラップできます。たとえば、呼び出しを記録できます。

function Log(target: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`[${key}]`, args);
    return original.apply(this, args);
  };
}

class Service {
  @Log
  greet(name: string) { return `Hello ${name}`; }
}

プロパティデコレーター

(target、key)を受け取ります。プロパティに関する情報を登録するため、reflect-metadataと組み合わせて使われることがよくあります。

function Required(target: any, key: string) {
  const existing = Reflect.getMetadata('required', target) || [];
  Reflect.defineMetadata('required', [...existing, key], target);
}

class User {
  @Required name: string;
  @Required email: string;
}

パラメーターデコレーター

(target、key、parameterIndex)を受け取ります。依存性注入で使用され、どのパラメータがどのサービスを必要とするかを記録します。

function Inject(token: string) {
  return function (target: any, key: string, index: number) {
    const existing = Reflect.getMetadata('inject', target, key) || {};
    existing[index] = token;
    Reflect.defineMetadata('inject', existing, target, key);
  };
}

class UserService {
  constructor(@Inject('Database') db: Database) {}
}

reflect-metadata

reflect-metadataは、デコレーターがクラスのメタデータを読み書きできるようにするポリフィルです。Angular DIや多くのORMで必要になります。

npm install reflect-metadata

// main.ts (entry point):
import 'reflect-metadata';

import { Reflect } from 'reflect-metadata';
Reflect.defineMetadata('key', 'value', target);
Reflect.getMetadata('key', target); // 'value'

デコレーターファクトリー

ファクトリーはデコレーターを返します。引数を渡すために使用します。

function Component(config: { selector: string }) {
  return function (target: any) {
    target.selector = config.selector;
  };
}

@Component({ selector: 'app-root' })
class AppComponent {}

バリデーションでの利用例

プロパティデコレーターとvalidate()関数を組み合わせて、小さなバリデーションライブラリを構築します。

// Decorator records that a field is required:
function Required(target: any, key: string) {
  const fields = Reflect.getMetadata('required', target) || [];
  Reflect.defineMetadata('required', [...fields, key], target);
}

class User {
  @Required name!: string;
  @Required email!: string;
}

function validate(obj: any): string[] {
  const required: string[] = Reflect.getMetadata('required', obj) || [];
  return required.filter(k => obj[k] == null);
}

Stage 3デコレーター(TC39)

標準化されたデコレーター(TS 5.0以降、Node 22以降ではフラグ付きでサポート)は、異なるシグネチャを持ちます。experimentalフラグは不要で、reflect-metadataも必要ありません。

デコレーターを使う場面

フレームワークが提供している場合はデコレーターを使用します(Angular、NestJS、TypeORMなど)。通常のフロントエンドコードで独自のデコレーターを作るのは避けます。複雑さが増し、特定のランタイム動作に依存することになるためです。

確認問題

メタデータリフレクションを伴うレガシー(experimental)デコレーターを使うには、どのtsconfigフラグを有効にする必要がありますか。

まとめ:デコレーター

デコレーターは、クラス、メソッド、プロパティ、パラメータを定義時に変更します。experimentalDecoratorsとemitDecoratorMetadataを有効にします。クラス、メソッド、プロパティ、パラメータのデコレーターではシグネチャが異なります。reflect-metadataはメタデータを保存し、ファクトリーは引数を渡します。Angular、NestJS、TypeORMで多用されています。Stage 3デコレーター(TS 5以降)が将来の標準で、フラグは必要ありません。

よくある質問

「デコレーターとメタデータ」レッスンは無料ですか?

はい。「デコレーターとメタデータ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Frontend Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Frontend Academyコースには全4レッスンが含まれています。

「デコレーターとメタデータ」で何を学びますか?

実験的なデコレーターを有効にし、クラス、メソッド、プロパティのデコレーターを記述して、依存性注入のパターンにreflect-metadataを使用します。 ブラウザで直接実行するハンズオンコードでFrontend Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Frontend Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのFrontend Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「デコレーターとメタデータ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このFrontend Academyレッスンでコードを書いて実行できますか?

はい。すべてのFrontend Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. テンプレートリテラル型
  2. デコレーターとメタデータ
  3. ReactとTypeScript:FC・ジェネリクス・フック
  4. Strictモードとanyの排除
← Frontend Academyに戻る