简体   繁体   中英

TypeScript decorator reports "Unable to resolve signature of class decorator when called as an expression"

@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()

When compile, it reports:

decorator.ts(1,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. Type '(msg: string) => any' is not assignable to type 'void'.

But the genrated js executed well. I don't know why it reports an error.

The compiler expects your decorator to either be void or return a value that is compatible with A. It sees that you return a (msg:any) => any but can not draw the conclusion that this function is compatible with A.

If you want to get rid of the error, you can cast the ff to any when you return it, or maybe even to typeof A to communicate the intention clearer:

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

That said, it's probably not a good idea to replace classes like this, you should at least maintain the constructor:

TypeScript documentation:

NOTE Should you chose to return a new constructor function, you must take care to maintain the original prototype. The logic that applies decorators at runtime will not do this for you.

This appears to be resolved by adding ES2016 or ES5 as the target in tsconfig.json

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

As mentioned by Alex above, the compiler expects your decorator to either be void or return a value that is compatible with A. So you can cast the ff to 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
}

For anyone that must have been facing this issue in 2022. It took me a long time but I realized that I was using an arrow functions. Decorators will not work on arrow functions. When I changed it, it worked smoothly.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM