Fehler: Es kann kein Ausdruck aufgerufen werden, dessen Typ keine Anrufsignatur aufweist

121

Ich bin brandneu im Typoskript und habe zwei Klassen. In der Elternklasse habe ich:

abstract class Component {
  public deps: any = {};
  public props: any = {};

  public setProp(prop: string): any {
    return <T>(val: T): T => {
      this.props[prop] = val;
      return val;
    };
  }
}

In der Kinderklasse habe ich:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

Sowohl showMore als auch ShowLess geben mir den Fehler "Kann keinen Ausdruck aufrufen, dessen Typ keine Aufrufsignatur hat."

Aber die Funktion, die setProp zurückgibt, hat eine Aufrufsignatur, denke ich? Ich glaube, ich verstehe etwas Wichtiges über die Eingabe von Funktionen falsch, aber ich weiß nicht, was es ist.

Vielen Dank!

Justin
quelle
1
togglrBodysollte keine Zeichenfolge sein, da Sie möchten, dass es eine Funktion ist
eavidan
1
@eavidan Ja, es ist eine Funktion, die tatsächlich einen Booleschen Wert zurückgibt. Ich dachte ursprünglich, es würde eine Zeichenfolge zurückgeben. Also, in was ändere ich es?
Justin
Was auch immer setProp zurückgibt, das scheint<T>(val: T) => T
eavidan

Antworten:

76

Die zurückgegebene Funktion hat eine Aufrufsignatur, aber Sie haben Typescript angewiesen, diese vollständig zu ignorieren, indem Sie : anydie Signatur hinzufügen .

Tu das nicht.

SLaks
quelle
Ok Fortschritt, danke! Jetzt erhalte ich "Fehler TS2322: Typ '<T> (val: T) => T' kann nicht dem Typ 'boolean' zugewiesen werden." Wenn ich das entferne: any. Ich denke, deshalb habe ich hinzugefügt: überhaupt keine. Ich bekomme eigentlich auch noch die Originalfehler.
Justin
1
Wenn ich das mache und es ändere public toggleBody: boolean;, public toggleBody: any;funktioniert es.
Justin
1
@ Justin, warum hast du etwas anderes erwartet? Sie behaupten, Sie this.toggleBodysollten zurückkehren boolean, aber das stimmt nicht mit dem Rückgabewert überein setProp, den Sie ihm zugewiesen haben. Sie scheinen nur zufällig Typen einzuwerfen, ohne darüber nachzudenken, was Sie tatsächlich senden und zurückgeben möchten.
Jonrsharpe
@ Jonrsharpe Ok ja das macht Sinn. In diesem Fall wird ein Boolescher Wert zurückgegeben, im Allgemeinen jedoch ein beliebiger. Also muss ich welche benutzen?
Justin
9
Diese Antwort würde davon profitieren, die richtige Vorgehensweise anhand eines Beispiels zu erläutern.
Andre M
37

"Ein Ausdruck, dessen Typ keine Anrufsignatur hat, kann nicht aufgerufen werden."

In Ihrem Code:

class Post extends Component {
  public toggleBody: string;

  constructor() {
    this.toggleBody = this.setProp('showFullBody');
  }

  public showMore(): boolean {
    return this.toggleBody(true);
  }

  public showLess(): boolean {
    return this.toggleBody(false);
  }
}

Du hast public toggleBody: string;. Sie können a nicht stringals Funktion aufrufen . Daher Fehler bei: this.toggleBody(true);undthis.toggleBody(false);

Basarat
quelle
28

Lassen Sie uns das zusammenfassen:

  1. Der Fehler sagt

    Ein Ausdruck, dessen Typ keine Anrufsignatur hat, kann nicht aufgerufen werden.

  2. Der Code:

Das Problem liegt in dieser Zeile public toggleBody: string;&

es ist die Beziehung zu diesen Zeilen:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. Das Ergebnis:

Ihr Sprichwort toggleBodyist ein, stringaber dann behandeln Sie es wie etwas, das ein hat call signature(dh die Struktur von etwas, das genannt werden kann: Lambdas, Proc, Funktionen, Methoden usw. In JS funktionieren Sie einfach tho.). Sie müssen die Deklaration ändern, um zu sein public toggleBody: (arg: boolean) => boolean;.

Zusätzliche Details:

"aufrufen" bedeutet, dass Sie eine Funktion aufrufen oder anwenden.

"ein Ausdruck" in Javascript ist im Grunde etwas, das einen Wert erzeugt, also this.toggleBody()als Ausdruck zählt.

In dieser Zeile wird "Typ" deklariert public toggleBody: string

"Fehlt eine Anrufsignatur" Dies liegt daran, dass Sie versuchen, etwas aufzurufen this.toggleBody(), das keine Signatur hat (dh die Struktur von etwas, das aufgerufen werden kann: Lambdas, Proc, Funktionen, Methoden usw.), das aufgerufen werden kann. Sie sagten, es this.toggleBodyist etwas, das sich wie eine Schnur verhält.

Mit anderen Worten, der Fehler sagt

Ein Ausdruck (this.toggleBody) kann nicht aufgerufen werden, da seinem Typ (: string) eine Aufrufsignatur fehlt (bc hat er eine String-Signatur.)

Taysky
quelle
4
Dies ist eine der besten Antworten aller Zeiten! Ich kenne all diese Definitionen, aber als ich die Warnmeldung sah, waren all diese Begriffe in einem dichten Satz zu viel für mein überladenes Gehirn.
Cham
6

Ich denke, was Sie wollen, ist:

abstract class Component {
  public deps: any = {};
  public props: any = {};

  public makePropSetter<T>(prop: string): (val: T) => T {
    return function(val) {
      this.props[prop] = val
      return val
    }
  }
}

class Post extends Component {
  public toggleBody: (val: boolean) => boolean;

  constructor () {
    super()
    this.toggleBody = this.makePropSetter<boolean>('showFullBody')
  }

  showMore (): boolean {
    return this.toggleBody(true)
  }

  showLess (): boolean {
    return this.toggleBody(false)
  }
}

Die wichtige Änderung ist in setProp(dh makePropSetterim neuen Code). Was Sie dort wirklich tun, ist zu sagen: Dies ist eine Funktion, die mit einem Eigenschaftsnamen versehen ist und eine Funktion zurückgibt, mit der Sie diese Eigenschaft ändern können.

Die <T>auf makePropSetterkönnen Sie diese Funktion , um eine bestimmte Art sperren. Der <boolean>Konstruktor in der Unterklasse ist tatsächlich optional. Da Sie zuweisen toggleBodyund der Typ bereits vollständig angegeben ist, kann der TS-Compiler ihn selbst erarbeiten.

Dann rufen Sie in Ihrer Unterklasse diese Funktion auf, und der Rückgabetyp wird nun ordnungsgemäß als Funktion mit einer bestimmten Signatur verstanden. Natürlich müssen Sie toggleBodydieselbe Unterschrift respektieren.

Andrew Miner
quelle
5

Es bedeutet, dass Sie versuchen, etwas aufzurufen, das keine Funktion ist

const foo = 'string'
foo() // error
Gunar Gessner
quelle
0

Fügen Sie Ihrer Variablen einen Typ hinzu und kehren Sie dann zurück.

Z.B:

const myVariable : string [] = ['hello', 'there'];

const result = myVaraible.map(x=> {
  return
  {
    x.id
  }
});

=> Wichtiger Teil ist das Hinzufügen des Typs string [] usw.:

Afshin Ghazi
quelle
0

Ich hatte die gleiche Fehlermeldung. In meinem Fall hatte ich versehentlich die ES6- export default function myFuncSyntax mit gemischt const myFunc = require('./myFunc');.

Die Verwendung von module.exports = myFunc;stattdessen löste das Problem.

Charlie Weems
quelle
0

Dieser Fehler kann verursacht werden, wenn Sie einen Wert von etwas anfordern und am Ende eine Klammer setzen, als wäre es ein Funktionsaufruf. Der Wert wird jedoch korrekt abgerufen, ohne die Klammer zu beenden. Wenn Sie beispielsweise auf eine Eigenschaft 'get' in Typescript zugreifen.

private IMadeAMistakeHere(): void {
    let mynumber = this.SuperCoolNumber();
}

private IDidItCorrectly(): void {
    let mynumber = this.SuperCoolNumber;
}

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
StackOverflowUser
quelle