typescript TS1241: Unable to resolve signature of method decorator when called as an expression
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 inf(): 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 ontypescriptlang.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 inf(): 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;
};
Jeff
Updated on February 12, 2020Comments
-
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 over 5 yearsIn my case, setting the target to
es2015
actually helped. -
Matthew Herbst over 5 yearsThanks! 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 about 4 yearsCan you explain why this happens?
-
Jason G about 4 yearsnot sure, but could have to do with bindings, () => {} auto binds
-
Astra Bear over 3 yearsThis is the only thing that worked for me. Setting traget ES5/es5/es2015 had no impact
-
Huan almost 3 yearsThis answer saves me twice.
-
user3453552 over 2 yearsspent 3 hours trying to figure what happened......u have the solution
-
user906573 over 2 yearsSame here. None of the other suggestions worked. This is the only one.