【问题标题】:Implementing JS decorator to wrap class实现 JS 装饰器来包装类
【发布时间】:2020-08-02 11:27:37
【问题描述】:

我正在尝试包装类构造函数并使用类装饰器注入一些逻辑。在我尝试扩展包装类之前一切正常:扩展类在原型中没有方法。

    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 中
  • 为什么不显示原始ts代码,而是帮助我们重现?顺便说一句,您在哪个环境中使用这些装饰器,因为 javascript 平台尚不支持此功能,或者您正在使用诸如 babel 之类的转译器?

标签: javascript typescript class-decorator


【解决方案1】:

好的,所以我试图找出你的代码有什么“错误”,但我无法让它工作,因为它没有进行类型检查。所以,作为最后的手段,我发布了我尝试的部分答案,它有效(有一些怪癖),所以我可以帮助其他更精通 TypeScript 的用户。

首先,怪癖:TS 中的类装饰器不能修改类型的结构,所以如果你想,例如,向被装饰的类添加一个方法,你可以做到,但你会在调用这些方法时吃掉/抑制不可避免的类型错误 (TS2339)。

在另一个问题中有一个解决方法:Typescript adding methods with decorator type does not exist,但是如果你这样做,你会失去这个当前干净的装饰器语法

现在,我的解决方案或多或少直接来自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();

【讨论】:

    猜你喜欢
    • 2016-04-08
    • 1970-01-01
    • 2019-07-12
    • 2021-07-16
    • 2016-04-29
    • 2011-06-26
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多