首页 > 解决方案 > 我在使用方法装饰器和类装饰器时遇到问题

问题描述

我有一个类装饰器,该类装饰器更改了类并在其中添加了一个属性。然后我有一个方法装饰器,它位于具有该类装饰器的类中,并且该方法装饰器试图访问由另一个装饰器创建的类中的属性。

// The Class Decorator
export function SomeDecorator(): ClassDecorator {
  return target => {
    target['property'] = { text: 'some text' };

    return target;
  }
}

// The Method Decorator
export function SomeOtherDecorator(): MethodDecorator {
  return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
    console.log(target['property'].text);
  }
}

// The Class
@SomeDecorator()
export class SomeClass {
  @SomeOtherDecorator()
  someMethod() {}
}

它会在运行时回答这个问题:TypeError: Cannot read property 'text' of undefined

为什么?

标签: typescriptdecorator

解决方案


就像提香所说,类装饰器在方法装饰器之后运行,这就是您的示例代码console.log(target['property'].text);失败的原因。

不确定您的实际用例,但如果您可以推迟对 的访问target['property'],则不会有任何问题。

function SomeOtherDecorator(): MethodDecorator {
  return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
    const fn = descriptor.value;
    // no problem, because `target['property']` is only accessed
    // when the decorated method (not decorator) is called.
    descriptor.value = (...args) => {
      console.log(target['property'].text);
      return fn.apply(target, args);
    };
  }
}

你甚至可以使用 getter 来懒惰地运行装饰器,应该照顾大多数用例。

function SomeOtherDecorator(): MethodDecorator {
  return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
    const fn = descriptor.value;
    let decoratedFn;
    descriptor.get = () => {
      if (decoratedFn) return decoratedFn;
      // do whatever you want to decorate the method/fn
      // including access to `target['property']`
      decoratedFn = ...
    }

推荐阅读