理解 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 中的一项关键功能,可以极大地改善您的开发工作流程,尤其是在大型应用程序中。