typescript TS1241:当作为表达式调用时,无法解析方法装饰器的签名

Jef*_*eff 18 decorator typescript

我的测试代码如下:

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

class Test {
    @test
    hello() {
    }
}
Run Code Online (Sandbox Code Playgroud)

但编译器给我错误

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.
Run Code Online (Sandbox Code Playgroud)

我已经指定:--experimentalDecorators --emitDecoratorMetadata

Dom*_*omQ 20

随着时间的推移,这个神秘的错误消息似乎有多个根本原因。截至 2019 年底,以下是我可以收集的信息:

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() { }
}
Run Code Online (Sandbox Code Playgroud)
  • 装饰器的调用约定及其类型取决于目标 JavaScript 方言。例如,运行上面的代码,{"compilerOptions": { "target": "ES3" } }结果是
    f(): 评估 main-2.js 行 1134 > eval:9:13
    g(): 评估 main-2.js 行 1134 > eval:15:13
    g(): 使用 2 个参数调用 main-2.js line 1134 > eval:17:17
    f():使用 2 个参数调用
    (在 上试用代码时typescriptlang.org/play,首先在浏览器的开发人员工具中打开 JavaScript 控制台;然后单击运行)。
    另一方面,"target": "ES5"结果下运行相同的代码
    f(): 评估 main-2.js 行 1134 > eval:9:13
    g(): 评估 main-2.js 行 1134 > eval:15:13
    g(): 使用 3 个参数调用 main-2.js line 1134 > eval:17:17
    f():使用 3 个参数调用
    
    因此,在这种情况下,TypeScript 对@f()(以及@g())完全满意。

因此最简单的解决方法是假装第三个参数是可选的,

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() { }
}
Run Code Online (Sandbox Code Playgroud)

"target": "ES3"和下都成功进行了类型检查"target": "ES5"

如果使用这种“欺骗”是特别重要的角流星,在这种情况下,你最肯定希望与混乱"target"的环境tsconfig.json


Dog*_*uca 18

似乎TypeScript期望装饰器函数的返回类型为"any"或"void".因此,在下面的示例中,如果我们添加: any到最后,它最终会起作用.

function test(target: Object, 
              propertyKey: string, 
              descriptor: TypedPropertyDescriptor<any>): any {
    return descriptor;
}
Run Code Online (Sandbox Code Playgroud)


Tuo*_* Le 12

使用 --target ES5 --emitDecoratorMetadata --experimentalDecorators

或使用以下配置:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "ES5"
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 就我而言,将目标设置为“es2015”实际上有所帮助。 (2认同)