Идентификация суперкласса Typescript от декоратора - PullRequest
1 голос
/ 28 февраля 2020

У меня есть абстрактный класс, подобный следующему

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 {
 @Bla
 public f1() {
 }
}

есть ли в декораторе способ различать guish, который вызывает источник из каждого суперкласса?

До сих пор я пытался проверить прототипы / конструкторы target, но я, похоже, не нашел способа получить доступ / понять, из какого класса он был получен. Есть ли способ выяснить это, или я делаю что-то действительно неправильно?

Спасибо.

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Хитрость в том, чтобы подключиться к самому вызову метода и проверить экземпляр класса:

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);
    }
  }
}
1 голос
/ 28 февраля 2020

Поскольку вы декорируете метод-прототип, декоратор применяется при оценке class конструкции, в которой находится декоратор, а не позже, когда создаются экземпляры. Он применяется только к члену-прототипу для этого класса (подклассы получают декорированный член только через наследование).

При условии, что у вас есть:

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 {
}

Декоратор будет работать при оценке class Foo , не позже, когда вы создаете экземпляры. Вы можете видеть, как это происходит на детской площадке . Если у вас есть этот код после приведенных выше определений классов:

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

Если вы декорируете элемент экземпляра, вы сможете различить, потому что экземпляр будет Boo или Moo, но не когда вы украшаете прототип члена.

...