【问题标题】:TypeScript decorator reports "Unable to resolve signature of class decorator when called as an expression"TypeScript 装饰器报告“作为表达式调用时无法解析类装饰器的签名”
【发布时间】:2016-07-26 13:57:36
【问题描述】:
@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()

编译时会报:

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

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

【问题讨论】:

  • 还要确保你用括号 () 调用 @Input(),因为它是一个函数。
  • 正如 STEEL 建议的那样,,, 这通常是您收到错误的原因。
  • 另请注意,装饰器不适用于箭头函数(对于函数装饰器)。 () =>

标签: typescript


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    正如上面 Alex 所说,编译器希望您的装饰器为 void 或返回与 A 兼容的值。因此您可以将 ff 强制转换为 typeof target

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        编译器希望您的装饰器为 void 或返回与 A 兼容的值。它看到您返回 (msg:any) => any,但无法得出此函数与 A 兼容的结论。

        如果您想摆脱错误,可以在返回时将 ff 强制转换为 any,甚至可以将其转换为 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
        }
        

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

        TypeScript documentation:

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

        【讨论】:

        • 非常感谢。铸造技术正是我所需要的。我不需要使用 进行双重转换, 就足够了。如果可以的话,我会支持你两次。
        • 您如何以通用方式执行此操作?如果我必须强制转换为我放置装饰器的类,我如何强制转换为放置装饰器的类型而不对类型进行硬编码?
        • @chubbsondubs 我也想这样做,但我认为我当时没有找到任何解决方案。也许我们现在有一些新的语法,我不知道。我认为问题之一是类的构造函数的类型对类的类型没有类型引用:github.com/Microsoft/TypeScript/issues/3841
        • 所以我阅读了装饰器提案,其中有一个示例不返回任何内容,因此不会替换构造函数。这将启用可以使用工厂装饰器模式获取参数的类级装饰器。但前提是您不想替换构造函数。
        • 这绝对是提案中的一个巨大漏洞,这可能也是为什么 Angular 2 仍然使用他们的注释模型而不是采用装饰器的原因。
        猜你喜欢
        • 2018-12-03
        • 2016-10-08
        • 2019-04-18
        • 2020-01-30
        • 2021-07-06
        • 1970-01-01
        • 2018-01-07
        • 2020-09-07
        • 2016-04-02
        相关资源
        最近更新 更多