返回

揭秘 TypeScript 装饰器的强大功能

前端

TypeScript 装饰器的全景

JavaScript 的装饰器还在提案阶段,但 TypeScript 已经基于该提案实现了自己的装饰器特性。装饰器模式是一种强大的元编程技术,它允许您在编译时修改代码的行为。

在 TypeScript 中,装饰器有四种类型:

  • 类装饰器
  • 方法装饰器
  • 参数装饰器
  • 属性装饰器

类装饰器

类装饰器用于修改类的行为。它接受一个类作为参数,并返回一个修改后的类。例如,以下装饰器将类标记为不可实例化:

function nonInstantiable(target: Function) {
  target.prototype.constructor = null;
}

@nonInstantiable
class MyClass {}

方法装饰器

方法装饰器用于修改方法的行为。它接受一个方法作为参数,并返回一个修改后的方法。例如,以下装饰器在方法调用前后记录日志:

function log(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with arguments:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`Method ${propertyKey} returned:`, result);
    return result;
  };
}

class MyClass {
  @log
  greet(name: string) {
    console.log(`Hello, ${name}!`);
  }
}

参数装饰器

参数装饰器用于修改方法参数的行为。它接受一个方法参数作为参数,并返回一个修改后的参数。例如,以下装饰器验证参数是否为非空:

function nonNull(target: Object, propertyKey: string | symbol, parameterIndex: number) {
  const originalMethod = target[propertyKey] as Function;
  target[propertyKey] = function (...args: any[]) {
    if (args[parameterIndex] === null) {
      throw new Error(`Argument ${parameterIndex} cannot be null`);
    }
    return originalMethod.apply(this, args);
  };
}

class MyClass {
  greet(@nonNull name: string) {
    console.log(`Hello, ${name}!`);
  }
}

属性装饰器

属性装饰器用于修改属性的行为。它接受一个属性作为参数,并返回一个修改后的属性。例如,以下装饰器为属性添加验证逻辑:

function validate(target: Object, propertyKey: string | symbol) {
  const originalGetter = Object.getOwnPropertyDescriptor(target, propertyKey)?.get;
  Object.defineProperty(target, propertyKey, {
    get: function () {
      const value = originalGetter?.call(this);
      if (value === undefined) {
        throw new Error(`Property ${propertyKey} cannot be undefined`);
      }
      return value;
    },
  });
}

class MyClass {
  @validate
  name: string | undefined;
}

总结

TypeScript 中的装饰器是一种强大的工具,它允许您在编译时增强代码的行为。通过理解不同类型的装饰器,您可以利用它们的优势来提高代码的可维护性、灵活性