【问题标题】:Accessing base class properties in derived class using prototype/Access base class properties in the decorator使用原型访问派生类中的基类属性/在装饰器中访问基类属性
【发布时间】:2019-08-23 14:15:55
【问题描述】:

我正在使用打字稿,并且正在为我的一个 Angular 类编写自定义装饰器。我想访问子类装饰器中的基类方法。或者使用子类原型访问基类方法。有没有办法做到这一点?问题在下面详细解释。

场景

我有一个类似的基类

export class Base {
    public init() {
        console.log('My base class function');
    }
}

我有一个派生类扩展了这个基类

export class Child extends Base {

}

我要做什么

我正在尝试为派生类编写一个装饰器,例如

@TestDecorator(['init'])
export class Child extends Base {

}

将从基类调用 init 方法

有什么问题

为了实现上述场景,我编写了如下代码

export function Tool<T extends Base>(methods: any[]) {
    return function (target: Function) {
        methods.forEach((item) => {
            if (item === 'init') {
                target.super.init() // Stuck here
            }
        })
    }
}

我不明白如何使以下行工作

target.super.init() // Stuck here

请帮助我解决问题。我被困住了。谢谢

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    我相信您正在寻找这样的东西:

    export function Tool<T extends Base>(methods: any[]) {
        return function (target: Function) {
            return class extends target {
                constructor(...args: any[]) {
                    super(...args)
                    methods.forEach((item) => {
                        if (item === 'init') {
                            super.init( );
                        }
                    })
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      为了扩展Paulpro's 的答案,由于装饰器函数返回的是它正在装饰的类的构造函数的替代品,它必须保持原始原型。

      在以下示例中,由于TestDecorator&lt;Base&gt; 中缺少init() 方法而导致错误。

      Typescript Playground Demo

      class Base {
        public init() {
          console.log('My base class function');
        }
      }
      
      function TestDecorator<T extends Base>(methods: any[]) {
        return function (target: any) {
          return class extends target {
            constructor(...args: any[]) {
              super(...args)
              methods.forEach((item) => {
                if (item === 'init') {
                  super.init( );
                }
              })
            }
          }
        }
      }
      
      @TestDecorator(['init'])  // Error: Property 'init' is missing in type 'TestDecorator<Base>.(Anonymous class)' but required in type 'Child'.
      class Child extends Base {
      
      }
      
      let c = new Child();
      

      更正的装饰器

      function TestDecorator<T extends Base>(methods: any[]) {
        return function (target: any) {
          return class extends target {
            init() {}  // Define init()
                  
            constructor(...args: any[]) {
              super(...args)
              methods.forEach((item) => {
                if (item === 'init') {
                  super.init( );
                }
              })
            }
          }
        }
      }
      
      

      Class Decorators

      如果类装饰器返回一个值,它将用提供的构造函数替换类声明。

      注意:如果您选择返回一个新的构造函数,您必须注意维护原始原型。在运行时应用装饰器的逻辑不会为您执行此操作。

      【讨论】:

        猜你喜欢
        • 2017-03-28
        • 1970-01-01
        • 1970-01-01
        • 2015-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多