简体   繁体   中英

Accessing base class properties in derived class using prototype/Access base class properties in the decorator

I am using typescript and i am writing a custom decorator for one of my angular class. I want to access the base class method in the child class decorator. Or access base class methods using the child class prototype. Is there any way to do this? Problem explained in detail below.

Scenario

I have a base class which is like

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

And i have a derived class which extends this base class

export class Child extends Base {

}

What i am trying to do

I am trying to write a decorator for the derived class something like

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

}

which will call the init method from the base class .

What is the issue

To do the above scenario, i have written code something like below

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

I am not understanding how to make the following line work

target.super.init() // Stuck here

Please help me with the solution. I am stuck. Thanks

I believe you are looking for something like this:

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( );
                    }
                })
            }
        }
    }
}

To expand on Paulpro's answer, since the decorator function is returning a substitute for the constructor of the class that it is decorating, it must maintain the original prototype.

In the following example, there is an error due to the missing init() method in TestDecorator<Base> .

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();

Corrected Decorator

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

If the class decorator returns a value, it will replace the class declaration with the provided constructor function.

NOTE: Should you choose to return a new constructor function, you must take care to maintain the original prototype. The logic that applies decorators at runtime will not do this for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM