TypeScript デコレータを理解する

TypeScript デコレータは、実行時にクラス、メソッド、プロパティ、パラメータに機能を追加する強力な手段を提供します。これらは、依存性注入、ログ記録、検証などの目的で Angular などのフレームワークでよく使用されます。この記事では、TypeScript のさまざまな種類のデコレータと、それらを効果的に使用する方法について説明します。

TypeScript デコレータとは何ですか?

TypeScript のデコレータは、先頭に @ 記号が付く関数で、クラス、メソッド、プロパティなどのさまざまな要素に添付できます。デコレータを使用すると、コードを直接変更することなく、添付されているコードの動作を変更できます。

デコレータの種類

  • クラス デコレータ: クラス全体に適用されます。
  • メソッド デコレータ: クラス内のメソッドに適用されます。
  • プロパティ デコレータ: クラス内のプロパティに適用されます。
  • パラメータ デコレータ: クラス内のメソッドのパラメータに適用されます。

TypeScript でデコレータを有効にする方法

デコレータを使用する前に、tsconfig.json ファイルで "experimentalDecorators"true に設定してデコレータを有効にしてください。

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

クラスデコレータ

クラス デコレータはクラス全体に適用されます。メタデータを追加したり、クラスの動作を変更したりする場合に役立ちます。

function Controller(route: string) {
  return function (target: Function) {
    target.prototype.route = route;
  };
}

@Controller('/api/user')
class UserController {
  // Class logic
}

console.log(new UserController().route); // Outputs: '/api/user'

メソッドデコレータ

メソッド デコレータは、クラス内のメソッドに適用されます。これらのデコレータを使用して、メソッドの動作を変更したり、ログに記録したりできます。

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

class Calculator {
  @Log
  add(a: number, b: number) {
    return a + b;
  }
}

const calculator = new Calculator();
calculator.add(2, 3); // Logs: 'Calling add with arguments: 2,3'

不動産デコレーター

プロパティ デコレータは、クラス内のプロパティに機能を追加するために使用されます。検証やプロパティへのメタデータの追加に役立ちます。

function ReadOnly(target: any, key: string) {
  const descriptor: PropertyDescriptor = {
    writable: false
  };
  return descriptor;
}

class Person {
  @ReadOnly
  name: string = 'John Doe';
}

const person = new Person();
person.name = 'Jane Doe'; // Error: Cannot assign to read only property 'name'

パラメータデコレータ

パラメータ デコレータは、メソッド パラメータに関する情報を変更またはログに記録するために使用されます。

function LogParameter(target: any, propertyName: string, index: number) {
  const metadataKey = `log_${propertyName}_parameters`;
  
  if (Array.isArray(target[metadataKey])) {
    target[metadataKey].push(index);
  } else {
    target[metadataKey] = [index];
  }
}

class Demo {
  method(@LogParameter param1: string, @LogParameter param2: number) {
    // Method logic
  }
}

結論

TypeScript のデコレータは、コードの構造を変更せずにコードの機能性を強化する強力な手段を提供します。クラス、メソッド、プロパティ、パラメータのデコレータの使い方を理解することで、ログ記録、検証、依存性注入などの高度な機能を実装できます。デコレータは、特に大規模なアプリケーションで開発ワークフローを大幅に改善できる TypeScript の重要な機能です。