typescript TS1241: Kan ikke løse signaturen til metode-dekoratør når den kalles som et uttrykk
Min testkode er som følger:
function test(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
return descriptor;
}
class Test {
@test
hello() {
}
}
men kompilatoren gir meg en feil
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.
Jeg har allerede spesifisert:
--experimentalDecorators --emitDecoratorMetadata
Svar #1
Bruk --target ES5 --emitDecoratorMetadata --experimentalDecorators
eller bruk følgende konfigurasjon:
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "ES5"
}
}
Svar #2
Det ser ut til at TypeScript forventer at returtypen til dekoratorfunksjonen skal være 'any' eller 'void'. Så i eksemplet nedenfor, hvis vi legger til : any på slutten, fungerer det til slutt.
function test(target: Object,
propertyKey: string,
descriptor: TypedPropertyDescriptor<any>): any {
return descriptor;
}
Svar #3
Denne kryptiske feilmeldingen ser ut til å ha hatt flere grunnårsaker over tid. Per slutten av 2019 er dette hva jeg kunne samle:
- Beskjeden er i beste fall misvisende; problemet har ingenting å gjøre med evnen til å løse signaturer, eller mangel på sådan. Den indikerer heller et typingsproblem på dekoratørene. For eksempel gir følgende kode TS1241 på
@f(), men ikke på@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() { }
}
Kallkonvensjonen for dekoratører, og dermed deres type, avhenger av den målrettede JavaScript-dialekten. For eksempel, å kjøre koden ovenfor med
{"compilerOptions": { "target": "ES3" } }resulterer if(): 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 argumentsf(): 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
(💡 Når du prøver ut koden på typescriptlang.org/play, åpne først JavaScript-konsollen i nettleserens utviklerverktøy; klikk deretter Kjør).
På den annen side, å kjøre nøyaktig den samme koden under "target": "ES5" resulterer i, og følgelig er TypeScript helt fornøyd med @f() (og også @g()) i det tilfellet.
Den enkleste løsningen er derfor å late som om den tredje parameteren er valgfri, det vil si
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() { }
}
som typekontrolleres vellykket både under "target": "ES3" og "target": "ES5".
Denne «juksen» er spesielt viktig hvis du bruker angular-meteor, i så fall vil du definitivt ikke rote med "target"-innstillingen i tsconfig.json.
