将装饰器与类构造器一起使用

时间:2019-10-30 15:36:18

标签: typescript typescript-decorator

我正在尝试在使用参数初始化的类中使用装饰器,但是当将装饰器应用于我的函数时,构造函数中设置的值未定义。请参见下面的玩具示例:

@ExperimentalContracts
fun stuff() {
   var possibleNull: String? = "test"
   if (testNull(possibleNull)) {
      mustPassNonNull(possibleNull)
   }
}

fun mustPassNonNull(possibleNull: String) {
   //use value that isn't null
}

@ExperimentalContracts
fun testNull(possibleNull: String?): Boolean {
   contract{
      returns(true) implies (possibleNull is String)
   }

   return possibleNull != null
}

我很想得到输出:

function someDecorator() {
  return (target: any, _2: any, descriptor: PropertyDescriptor) => {
    const func = descriptor.value.bind(target);
    descriptor.value = () => {
      console.log('Doing decorator stuff!');
      func();
    }
  }
}

class Foo {

  public constructor(private thing: string) { }

  @someDecorator()
  bar() {
    console.log(this.thing);
  }
}

new Foo('Hello world!').bar();

可惜我得到了输出:

> Doing decorator stuff!
> Hello world!

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:2)

您获得的target将是该类的原型,而不是任何实例。因此,将方法绑定到target将会失去实际实例的this上下文,而是在原型的上下文中调用它,而原型通常没有任何这些实例属性。

您必须等到实际调用类方法后才能获得适当的this。因此,请忘记target,而是将func绑定到新方法中的this上。并请注意,箭头函数将没有自己的this,因此descriptor.value不应是箭头函数(没有更多的箍跳)。因此,我建议使用传统的匿名function。因此,将someDecorator()的实现更改为以下内容:

function someDecorator() {
  return (target: any, _2: any, descriptor: PropertyDescriptor) => {
    const func = descriptor.value; // don't bind here
    descriptor.value = function (...args: any) {
      console.log('Doing decorator stuff!');
      func.apply(this, args); // bind here (applying args is optional I guess)
    }
  }
}

现在应该可以使用:

new Foo('Hello world!').bar(); 
// Doing decorator stuff!
// Hello world!

希望有帮助。祝你好运!

Link to code