Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

144
Views
Properties are undefined within a decorator

I am trying to call a function that that has a decorator attached to it. What it does is run every x seconds which works just fine, however, when I try to log the properties in the function they output undefined, but in the constructor it displays the proper class.

If I call another function that is in the class, the function gets called, the issue just seems to be when accessing properties.

Here are a few of the ways I have tried to call the method:

export function Repeat(interval: number, delay: number = 0) {
  return (target: any, prop: any, descriptor: PropertyDescriptor) => {

    timer(delay * 1000, interval * 1000)
      .pipe(
        tap(i => descriptor.value.call(target, i)),
        tap(i => target[prop].call(target, i)),
        tap(i => target[prop].bind(target)(i))
      )
      .subscribe();

  };
}

Here is how I am implementing the decorator:

export class MyClass {

  constructor(private readonly v: Item) { 
    console.log(this.v); // outputs: typeof Item
  }

  @Repeat(1)
  repeat(count: number) {
    console.log(this.v); // outputs: undefined
    this.testFunc(); // runs the function
  }

  testFunc(){
    console.log('test function');
  }
}

Here is a stackblitz example

Edit

After playing for a bit, I can see that I can do this:

export function Repeat(interval: number, delay = 0) {
  return function (target: any, prop: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = function (this: GameObject, ...args: any[]) {
      const t = timer(delay * 1000, interval * 1000)
        .pipe(map<number, boolean>(i => originalMethod.apply(this, [i])))
        .subscribe();
    };
    return descriptor;
  };
}

Then when I call it in the class the repeater works:

export class MyClass {

  constructor(private readonly v: Item) { 
    this.repeat(0);
  }

  @Repeat(1)
  repeat(count: number) {
    console.log(this.v); // outputs: typeof Item
  }
}

However, this is not what I want to resort to, I would like the function to be called automatically and not manually.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

So, to solve my issue I had to use a decorator at the class level along with at the method level. Then, in the constructor I run the method on the parent class.

First import the reflect-metadata module:

import 'reflect-metadata';
export function Component() {
  return <T extends { new (...args: any[]): any }>(target: T): any => {
    return class extends target {
      constructor(...args: any[]) {
        super(...args);
        const methods = Reflect.ownKeys(target.prototype) as string[];
        methods.forEach((method) => {
          // Get the saved metadata
          const r = Reflect.getMetadata('token', target.prototype, method);
          if (typeof r === 'function') {
            // Here is where we call the method.
            this[method]();
          }
        });
      }
    };
  };
}

Here is the repeat function:

export function Repeat(interval: number, delay = 0, times = Infinity) {
  return function (target: any, prop: string, descriptor: PropertyDescriptor) {
    // Define the metadata to be used for later
    Reflect.defineMetadata('token', target[prop], target, prop);
    const originalMethod = descriptor.value;
    descriptor.value = function (this: any, ...args: any[]) {
      timer(delay * 1000, interval * 1000)
        .pipe(map<number, boolean>((i) => originalMethod.apply(this, [i])))
        .subscribe();
    };
    return descriptor;
  };
}

Here is how it is implemented in the class:

@Component()
export class MyClass {

  constructor(private readonly v: Item) { 
    console.log(this.v); // outputs: typeof Item
  }

  @Repeat(1)
  repeat(count: number) {
    console.log(this.v); // outputs: typeof Item
  }
}

Here is the stackblitz example.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!