TypeScript装饰器报告"当作为表达式调用时无法解析类装饰器的签名"

clo*_*oud 36 typescript

@xxx("xxx")
class A{
    msg:string
    constructor(msg:string) {
        this.msg = msg
    }
    print() {
        console.log(this.msg)
    }
}

function xxx(arg:string) {
    function f(target) {
        function ff(msg: string) {
            return new target(arg + ":" + msg)
        }
        return ff
    }
    return f
}

let a = new A("hellow")
a.print()
Run Code Online (Sandbox Code Playgroud)

编译时,报告:

decorator.ts(1,1):错误TS1238:当作为表达式调用时,无法解析类装饰器的签名.类型'(msg:string)=> any'不能分配给'void'类型.

但是生成的js执行得很好.我不知道为什么报错.

sig*_*lor 35

我的问题是,我的 tsconfig.json"experimentalDecorators": true中仍然有compilerOptions,但在最新版本的 TypeScript 中不再需要它。


Ale*_*lex 13

编译器期望你的装饰器要么为空,要么返回一个与A兼容的值.它看到你返回一个(msg:any) => any但不能得出这个函数与A兼容的结论.

如果你想摆脱这个错误,你可以在返回时将ff转换为任何一个,或者甚至可以typeof A更清楚地传达意图:

function xxx(arg: string)
{
    function f(target)
    {
        function ff(msg: string)
        {
            return new target(arg + ":" + msg)
        }
        return <typeof A><any>ff
    }
    return f
}
Run Code Online (Sandbox Code Playgroud)

也就是说,替换这样的类可能不是一个好主意,你至少应该维护构造函数:

TypeScript文档:

注意如果您选择返回新的构造函数,则必须注意维护原始原型.在运行时应用装饰器的逻辑不会为您执行此操作.


小智 9

我遇到了类似的问题,发现我在 VS Code 中选择了 src 文件夹而不是项目文件夹。一旦我选择项目文件夹作为根目录,tsconfig.json 文件就被识别出来,错误就消失了。


小智 8

在Vue+Vite上需要添加:

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

到 tsconfig. 应用程序.json,而不是 tsconfig.json。


URL*_*L87 7

似乎可以通过在tsconfig.json中添加ES2016或ES5作为目标来解决

https://github.com/alsatian-test/alsatian/issues/344#issuecomment-290418311


Jer*_*iah 6

对于 2022 年一定遇到过这个问题的人来说。我花了很长时间,但我意识到我正在使用箭头函数。装饰器不适用于箭头函数。当我改变它时,它运行得很顺利。


沈晖莹*_*沈晖莹 6

我收到类似的错误消息:

作为表达式调用时无法解析类装饰器的签名。运行时将使用 2 个参数调用装饰器,但装饰器需要 1.ts(1238)

我的 Typescript 版本是5.0.4。我通过将其添加到 tsconfig.json 解决了这个问题:

{
  "compilerOptions": {
    "experimentalDecorators": true, // the key line
  },
}
Run Code Online (Sandbox Code Playgroud)