Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript decorator - accepts too few arguments to be used as a decorator here

Tags:

typescript

I am trying to write a decorator that accepts a method and throws an error if the method did not complete in the specified timeout (specified using the method arguments). Not specifying a timeout should result in the method running as if the argument is not there.

export const setMethodTimeout = (): Function => {
  return function(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
    const context = this;
    const args: DecoratorArgumentType = arguments;
    if (args.timeout) {
      const timer = setTimeout(() => {
        throw new Error('The method did not finish before the specified timeout.');
      }, args.timeout);
      const originalMethod = descriptor.value;
      descriptor.value = function() {
        originalMethod
          .apply(context, args)
          .then((result: any) => {
            clearTimeout(timer);
            return result;
          })
          .catch((e: Error) => {
            throw e;
          });
      };
    }
    return descriptor;
  };
};

Now when I try to use this decorator on my class method:

@setMethodTimeout
public async getMap(params: GetMapParams, api: ApiType, reqConfig?: RequestConfiguration): Promise<Blob> {
   //...
}

I get the following typescript error:

‘setMethodTimeout’ accepts too few arguments to be used as a decorator here. Did you mean to call it first and write ‘@setMethodTimeout()’?

Why is this happening?

like image 230
Miha Šušteršič Avatar asked Dec 02 '25 10:12

Miha Šušteršič


1 Answers

It requires a function call since you are wrapping the decorator with additional function setMethodTimeout. It will work without the function call syntax if you remove it like this:

export const function setMethodTimeout(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
    const context = this;
    const args: DecoratorArgumentType = arguments;
    if (args.timeout) {
      const timer = setTimeout(() => {
        throw new Error('The method did not finish before the specified timeout.');
      }, args.timeout);
      const originalMethod = descriptor.value;
      descriptor.value = function() {
        originalMethod
          .apply(context, args)
          .then((result: any) => {
            clearTimeout(timer);
            return result;
          })
          .catch((e: Error) => {
            throw e;
          });
      };
    }
    return descriptor;
};
like image 79
pbn Avatar answered Dec 04 '25 03:12

pbn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!