我在方法装饰器和类装饰器方面遇到问题

时间:2019-04-21 16:31:18

标签: typescript decorator

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

// 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:无法读取未定义的属性“文本”

为什么?

1 个答案:

答案 0 :(得分:0)

就像提香说的那样,类装饰器在方法装饰器之后运行,这就是您的示例代码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 = ...
    }