typescript TS1241: Unable to resolve signature of method decorator when called as an expression

27,449

Solution 1

It seems that TypeScript expects the return type of the decorator function to be 'any' or 'void'. So in the example below, if we add : any to the end, it ends up working.

function test(target: Object, 
              propertyKey: string, 
              descriptor: TypedPropertyDescriptor<any>): any {
    return descriptor;
}

Solution 2

Use --target ES5 --emitDecoratorMetadata --experimentalDecorators

or use the following config:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "ES5"
  }
}

Solution 3

This cryptic error message seems to have had multiple root causes over time. As of end of 2019, here is what I could gather:

  • The message is misleading at best; the problem has nothing to do with ability to resolve signatures, or lack thereof. Rather, it signals a typing problem on the decorators. For instance, the following code signals TS1241 at @f(), but not at @g():
function f() {
    console.log("f(): evaluated");
    return function (targetClass: any, propertyKey: string, descriptor: TypedPropertyDescriptor<() => void>) {
        console.log("f(): called with " + arguments.length + " arguments");
    }
}

function g() {
    console.log("g(): evaluated");
    return function (target: any, propertyKey: string) {
        console.log("g(): called with " + arguments.length + " arguments");
    }
}

class C {
    @f()      // TypeScript signals TS1241 here
    @g()      // but not there
    method() { }
}
  • The calling convention on decorators, and therefore their type, depends on the targeted JavaScript dialect. For instance, running the above code with {"compilerOptions": { "target": "ES3" } } results in
    f(): evaluated main-2.js line 1134 > eval:9:13
    g(): evaluated main-2.js line 1134 > eval:15:13
    g(): called with 2 arguments main-2.js line 1134 > eval:17:17
    f(): called with 2 arguments
    (💡 When trying out the code on typescriptlang.org/play, first open the JavaScript console in your browser's Developer Tools; then click Run).
    On the other hand, running the very same code under "target": "ES5" results in
    f(): evaluated main-2.js line 1134 > eval:9:13
    g(): evaluated main-2.js line 1134 > eval:15:13
    g(): called with 3 arguments main-2.js line 1134 > eval:17:17
    f(): called with 3 arguments
    
    and accordingly, TypeScript is fully happy with @f() (and also @g()) in that case.

The simplest workaround is therefore to pretend that the third parameter is optional, i.e.

function f() {
    console.log("f(): evaluated");
    return function (targetClass: any, propertyKey: string, descriptor?: TypedPropertyDescriptor<() => void>) {
        console.log("f(): called with " + arguments.length + " arguments");
    }
}

class C {
    @f()
    method() { }
}

which type-checks successfully under both "target": "ES3" and "target": "ES5".

This “cheat” is especially important if using angular-meteor, in which case you most definitely do not want to mess with the "target" setting in tsconfig.json.

Solution 4

You can also get this error if you are using

() => {}

function notation, switch to regular notation

function() {}

Solution 5

Add this command in tsconfig for use decorator.

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "ES5"
  }
}

Decorator function should like this.

function(target: any, key: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
    descriptor.value = async function(...args: any) {
      try {
        const result = await originalMethod.apply(this, args);
        return result;
      } catch (error) {
         console.log(error)
      }
    };

    return descriptor;
  };
Share:
27,449
Jeff
Author by

Jeff

Updated on February 12, 2020

Comments

  • Jeff
    Jeff over 4 years

    My test code is like the following:

    function test(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        return descriptor;
    }
    
    class Test {
        @test
        hello() {
        }
    }
    

    but the compiler give me error

    Error:(33, 5) TS1241: Unable to resolve signature of method decorator when called as an expression.
     Supplied parameters do not match any signature of call target.
    

    I have already specified: --experimentalDecorators --emitDecoratorMetadata

  • Slava Fomin II
    Slava Fomin II over 5 years
    In my case, setting the target to es2015 actually helped.
  • Matthew Herbst
    Matthew Herbst over 5 years
    Thanks! For others: I was able to get this working (in a JS project) by using "allowJs": true. I didn't need to use "target": "ES5"
  • joao-m-santos
    joao-m-santos about 4 years
    Can you explain why this happens?
  • Jason G
    Jason G about 4 years
    not sure, but could have to do with bindings, () => {} auto binds
  • Astra Bear
    Astra Bear over 3 years
    This is the only thing that worked for me. Setting traget ES5/es5/es2015 had no impact
  • Huan
    Huan almost 3 years
    This answer saves me twice.
  • user3453552
    user3453552 over 2 years
    spent 3 hours trying to figure what happened......u have the solution
  • user906573
    user906573 over 2 years
    Same here. None of the other suggestions worked. This is the only one.