实现 JS 装饰器来包装 class
Implementing JS decorator to wrap class
我正在尝试包装 class 构造函数并使用 class 装饰器注入一些逻辑。一切正常,直到我尝试扩展包装 class:扩展 class 原型中没有方法。
function logClass(Class) {
// save a reference to the original constructor
const _class = Class;
// proxy constructor
const proxy = function(...args) {
const obj = new _class(...args);
// ... add logic here
return obj
}
// copy prototype so intanceof operator still works
proxy.prototype = _class.prototype;
// return proxy constructor (will override original)
return proxy;
}
@logClass
class Base {
prop = 5;
test() {
console.log("test")
}
}
class Extended extends Base {
test2() {
console.log("test2")
}
}
var base = new Base()
base.test()
var ext = new Extended()
console.log(ext.prop)
ext.test()
ext.test2() // TypeError: ext.test2 is not a function
好的,所以我试图弄清楚您的代码有什么“错误”,但我无法让它工作,因为它没有进行类型检查。所以,作为最后的手段,我发布了我尝试的部分答案,它有效(有一些怪癖)所以我可以帮助其他更精通 TypeScript 的用户。
首先,怪癖:classTS中的装饰器不能修改类型的结构,所以如果你想,比如给装饰的class添加一个方法,你可以做到,但是在调用这些方法时你将不得不吃 up/suppress 不可避免的类型错误 (TS2339)。
在另一个问题中有解决此问题的方法:,但是如果您这样做,您将失去装饰器的当前干净语法。
现在,我的解决方案或多或少直接取自 documentation:
function logClass<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
constructor(...args: any[]) {
super(args);
// ...add programmatic logic here
// (`super` is the decorated class, of type `T`, here)
}
// ...add properties and methods here
log(message: string) { // EXAMPLE
console.log(`${super.constructor.name} says: ${message}`);
}
}
}
@logClass
class Base {
prop = 5;
test() {
console.log("test");
}
constructor() {}
}
class Extended extends Base {
test2() {
console.log("test2");
}
}
var base = new Base();
base.test();
var ext = new Extended();
console.log(ext.prop);
//base.log("Hello"); // unavoidable type error TS2339
ext.test();
ext.test2();
我正在尝试包装 class 构造函数并使用 class 装饰器注入一些逻辑。一切正常,直到我尝试扩展包装 class:扩展 class 原型中没有方法。
function logClass(Class) {
// save a reference to the original constructor
const _class = Class;
// proxy constructor
const proxy = function(...args) {
const obj = new _class(...args);
// ... add logic here
return obj
}
// copy prototype so intanceof operator still works
proxy.prototype = _class.prototype;
// return proxy constructor (will override original)
return proxy;
}
@logClass
class Base {
prop = 5;
test() {
console.log("test")
}
}
class Extended extends Base {
test2() {
console.log("test2")
}
}
var base = new Base()
base.test()
var ext = new Extended()
console.log(ext.prop)
ext.test()
ext.test2() // TypeError: ext.test2 is not a function
好的,所以我试图弄清楚您的代码有什么“错误”,但我无法让它工作,因为它没有进行类型检查。所以,作为最后的手段,我发布了我尝试的部分答案,它有效(有一些怪癖)所以我可以帮助其他更精通 TypeScript 的用户。
首先,怪癖:classTS中的装饰器不能修改类型的结构,所以如果你想,比如给装饰的class添加一个方法,你可以做到,但是在调用这些方法时你将不得不吃 up/suppress 不可避免的类型错误 (TS2339)。
在另一个问题中有解决此问题的方法:
现在,我的解决方案或多或少直接取自 documentation:
function logClass<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
constructor(...args: any[]) {
super(args);
// ...add programmatic logic here
// (`super` is the decorated class, of type `T`, here)
}
// ...add properties and methods here
log(message: string) { // EXAMPLE
console.log(`${super.constructor.name} says: ${message}`);
}
}
}
@logClass
class Base {
prop = 5;
test() {
console.log("test");
}
constructor() {}
}
class Extended extends Base {
test2() {
console.log("test2");
}
}
var base = new Base();
base.test();
var ext = new Extended();
console.log(ext.prop);
//base.log("Hello"); // unavoidable type error TS2339
ext.test();
ext.test2();