从装饰器识别的 Typescript 超类
Typescript superclass identifying from a decorator
我有一个摘要class如下
export abstract class Foo {
public f1() {
}
}
和另外两个 classes 扩展基础
export class Boo extends Foo {
}
export class Moo extends Foo {
}
现在我有一个像下面这样的自定义装饰器
export function Bla() {
return (target: any, key: string, descriptor: PropertyDescriptor) => {
}
}
所以我的初始 class 如下(带有装饰器)
export abstract class Foo {
@Bla
public f1() {
}
}
装饰器中有没有办法区分哪个调用来自每个超级class?
到目前为止,我所尝试的是检查 target
的原型/构造函数,但我似乎没有找到一种方法来访问/理解它的来源 class。有没有办法弄清楚,或者我做错了什么?
谢谢。
因为您正在装饰原型方法,所以当 class
对装饰器所在的构造进行求值时应用装饰器,而不是稍后创建实例时应用装饰器。它仅适用于 class 的原型成员(subclasses 仅通过继承获得装饰成员)。
假设您有:
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
计算时 运行,而不是稍后创建实例时。你可以看到这种情况发生 in the playground。如果您在上面的 class 定义之后有此代码:
setTimeout(() => {
new Boo; // Nothing shows in the console
setTimeout(() => {
new Moo; // Nothing shows in the console
console.log("Done");
}, 1000);
}, 1000);
如果您正在装饰一个实例成员,您将能够区分,因为该实例将是 Boo
或 Moo
,但在您装饰原型成员时则不然。
它的诀窍是利用方法调用本身并检查 class 实例:
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);
}
}
}
我有一个摘要class如下
export abstract class Foo {
public f1() {
}
}
和另外两个 classes 扩展基础
export class Boo extends Foo {
}
export class Moo extends Foo {
}
现在我有一个像下面这样的自定义装饰器
export function Bla() {
return (target: any, key: string, descriptor: PropertyDescriptor) => {
}
}
所以我的初始 class 如下(带有装饰器)
export abstract class Foo {
@Bla
public f1() {
}
}
装饰器中有没有办法区分哪个调用来自每个超级class?
到目前为止,我所尝试的是检查 target
的原型/构造函数,但我似乎没有找到一种方法来访问/理解它的来源 class。有没有办法弄清楚,或者我做错了什么?
谢谢。
因为您正在装饰原型方法,所以当 class
对装饰器所在的构造进行求值时应用装饰器,而不是稍后创建实例时应用装饰器。它仅适用于 class 的原型成员(subclasses 仅通过继承获得装饰成员)。
假设您有:
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
计算时 运行,而不是稍后创建实例时。你可以看到这种情况发生 in the playground。如果您在上面的 class 定义之后有此代码:
setTimeout(() => {
new Boo; // Nothing shows in the console
setTimeout(() => {
new Moo; // Nothing shows in the console
console.log("Done");
}, 1000);
}, 1000);
如果您正在装饰一个实例成员,您将能够区分,因为该实例将是 Boo
或 Moo
,但在您装饰原型成员时则不然。
它的诀窍是利用方法调用本身并检查 class 实例:
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);
}
}
}