从装饰程序识别的Typescript超类

从装饰程序识别的Typescript超类,typescript,superclass,typescript-decorator,Typescript,Superclass,Typescript Decorator,我有一个抽象类,如下所示 export abstract class Foo { public f1() { } } 还有两个扩展基的类 export class Boo extends Foo { } export class Moo extends Foo { } 现在我有一个定制的装饰器,如下所示 export function Bla() { return (target: any, key: string, descriptor: PropertyDescriptor

我有一个抽象类,如下所示

export abstract class Foo {
  public f1() {
  }
}
还有两个扩展基的类

export class Boo extends Foo {
}

export class Moo extends Foo {
}
现在我有一个定制的装饰器,如下所示

export function Bla() {
  return (target: any, key: string, descriptor: PropertyDescriptor) => {
  }
}
所以我的第一堂课是(与装饰师一起)

decorator中是否有方法区分来自每个超类的调用

到目前为止,我尝试的是检查
target
的原型/构造函数,但我似乎没有找到一种方法来访问/理解它来自哪个类。有没有办法弄清楚,或者我真的做错了什么


谢谢。

因为您正在装饰一个原型方法,所以在评估装饰器所处的
构造时应用装饰器,而不是稍后创建实例时应用。它仅应用于该类的原型成员(子类仅通过继承获得修饰成员)

假设你有:

function Bla() {
  return (target: any, key: string, descriptor: PropertyDescriptor) => {
    console.log(target.constructor.name);
  }
}

abstract class Foo {
  @Bla()
  public f1() {
  }
}

// At this point, you see "Foo" in the console

class Boo extends Foo {
}

class Moo extends Foo {
}
decorator将在计算
类Foo
时运行,而不是稍后创建实例时运行。你可以看到这种情况发生。如果在上述类定义之后有此代码:

setTimeout(() => {
    new Boo; // Nothing shows in the console
    setTimeout(() => {
        new Moo; // Nothing shows in the console
        console.log("Done");
    }, 1000);
}, 1000);

如果您装饰一个实例成员,您将能够进行区分,因为该实例将是
Boo
Moo
,但当您装饰一个原型成员时就不是了。

它的诀窍是点击方法调用本身并检查类实例:

function Bla(target: any, propKey: string | symbol | d: PropertyDescriptor) {
  let originalMethod = target[propKey];

  // return new property descriptor for the method, replacing the original one
  return {
    value: function () {
      let instance = this; // will be the instance ref because of 'function' literal
      let classReference = instance.constructor; // <-- this is what we need

      if (classReference === Boo) {
        // called from Boo class
      }

      // call original method
      return originalMethod.apply(this, arguments);
    }
  }
}
函数Bla(目标:any,propKey:string | symbol | d:PropertyDescriptor){
让originalMethod=target[propKey];
//返回方法的新属性描述符,替换原始属性描述符
返回{
值:函数(){
let instance=this;//将是实例引用,因为'function'文本

让classReference=instance.constructor;//Ye我的问题实际上仍然让人困惑。很抱歉(您为类装饰器解释的内容已经给了我一个提示),我想区分
new Boo().f1()
new Moo().f1()
。应用于函数的装饰器规则与应用于类的装饰器规则相同?@MichaelMichailidis-通过查看调用中的
this
,您可以区分
new Boo().f1()
new Moo().f1()
。如果您不想依赖
this
(由于
Function.prototype.call/apply
,它可以是任何东西),因此必须重写子类中的
f1
(然后可能使用
super.f1()
调用子类中的超类版本)。
function Bla(target: any, propKey: string | symbol | d: PropertyDescriptor) {
  let originalMethod = target[propKey];

  // return new property descriptor for the method, replacing the original one
  return {
    value: function () {
      let instance = this; // will be the instance ref because of 'function' literal
      let classReference = instance.constructor; // <-- this is what we need

      if (classReference === Boo) {
        // called from Boo class
      }

      // call original method
      return originalMethod.apply(this, arguments);
    }
  }
}