Errore: impossibile richiamare un'espressione il cui tipo non dispone di una firma di chiamata


121

Sono nuovo di zecca nel dattiloscritto e ho due classi. Nella classe genitore ho:

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;
    };
  }
}

Nella classe bambino ho:

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);
  }
}

Sia showMore che ShowLess restituiscono l'errore "Impossibile richiamare un'espressione il cui tipo non dispone di una firma di chiamata".

Ma la funzione restituita da setProp HA una firma di chiamata, credo? Penso di aver frainteso qualcosa di importante sulla digitazione delle funzioni, ma non so cosa sia.

Grazie!


1
togglrBodynon dovrebbe essere una stringa, dal momento che vuoi che sia una funzione
eavidan

1
@eavidan sì, è una funzione che in realtà restituisce un booleano. Inizialmente pensavo che avrebbe restituito una stringa. Allora in cosa lo cambio?
Justin

Qualunque cosa restituisca setProp, che sembra <T>(val: T) => T
eavidan

Risposte:


76

La funzione che restituisce ha una firma di chiamata, ma hai detto a Typescript di ignorarla completamente aggiungendo : any sua firma.

Non farlo.


Ok progressi, grazie! Ora ottengo "errore TS2322: il tipo '<T> (val: T) => T' non è assegnabile al tipo 'booleano'." Se rimuovo: any. Penso che questo sia il motivo per cui ho aggiunto: any in primo luogo. In realtà ricevo ancora gli errori originali.
Justin,

1
Se faccio questo e il cambiamento public toggleBody: boolean;a public toggleBody: any;funziona.
Justin

1
@Justin perché ti aspettavi qualcos'altro? La tua richiesta this.toggleBodydovrebbe restituire boolean, ma non è coerente con il valore di ritorno di setPropquello che gli hai assegnato. Sembra che tu stia solo gettando casualmente dei tipi senza pensare a ciò che vuoi effettivamente inviare e restituire.
jonrsharpe

@jonrsharpe Ok, sì, ha senso. In questo caso restituisce un booleano, ma in generale restituisce any. Quindi devo usarne uno?
Justin

9
Questa risposta trarrebbe vantaggio dallo spiegare il modo giusto di fare le cose, con un esempio.
Andre M

38

"Impossibile richiamare un'espressione il cui tipo non dispone di una firma di chiamata."

Nel tuo codice:

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);
  }
}

Hai public toggleBody: string;. Non puoi chiamare a stringcome funzione. Quindi errori su: this.toggleBody(true);ethis.toggleBody(false);


28

Analizziamo questo:

  1. L'errore dice

    Impossibile richiamare un'espressione il cui tipo non dispone di una firma di chiamata.

  2. Il codice:

Il problema è in questa linea public toggleBody: string; e

è in relazione a queste linee:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. Il risultato:

Il tuo modo di dire toggleBodyè a stringma poi lo tratti come qualcosa che ha un call signature(cioè la struttura di qualcosa che può essere chiamato: lambda, proc, funzioni, metodi, ecc. In JS solo funzione tho.). È necessario modificare la dichiarazione in essere public toggleBody: (arg: boolean) => boolean;.

Dettagli extra:

"invocare" significa chiamare o applicare una funzione.

"un'espressione" in Javascript è fondamentalmente qualcosa che produce un valore, quindi this.toggleBody()conta come espressione.

"tipo" è dichiarato su questa riga public toggleBody: string

"manca una firma di chiamata" questo è perché stai cercando di chiamare qualcosa this.toggleBody()che non ha firma (cioè la struttura di qualcosa che può essere chiamato: lambda, proc, funzioni, metodi, ecc.) che può essere chiamato. Hai detto che this.toggleBodyè qualcosa che agisce come una corda.

In altre parole, sta dicendo l'errore

Impossibile chiamare un'espressione (this.toggleBody) perché il suo tipo (: string) manca di una firma di chiamata (bc ha una firma di stringa).


4
Questa è una delle migliori risposte, mai! Conosco tutte quelle definizioni, ma quando ho visto il messaggio di avvertimento tutti quei termini, in una frase densa, erano troppo per il mio cervello disordinato.
cham

6

Penso che quello che vuoi è:

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)
  }
}

Il cambiamento importante è in setProp(cioè, makePropSetternel nuovo codice). Quello che stai facendo davvero è dire: questa è una funzione, che fornita con un nome di proprietà, restituirà una funzione che ti permette di cambiare quella proprietà.

L' <T>on makePropSetterconsente di bloccare quella funzione per un tipo specifico. Il <boolean>costruttore della sottoclasse è in realtà opzionale. Dal momento che stai assegnando atoggleBody , e che ha già il tipo completamente specificato, il compilatore TS sarà in grado di risolverlo da solo.

Quindi, nella tua sottoclasse, chiami quella funzione e il tipo restituito è ora correttamente inteso come una funzione con una firma specifica. Naturalmente, dovrai toggleBodyrispettare quella stessa firma.


5

Significa che stai cercando di chiamare qualcosa che non è una funzione

const foo = 'string'
foo() // error

0

Aggiungi un tipo alla tua variabile e poi torna.

Per esempio:

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

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

=> La parte importante è l'aggiunta della stringa [] tipo ecc:


0

Ho ricevuto lo stesso messaggio di errore. Nel mio caso avevo inavvertitamente mescolato la export default function myFuncsintassi di ES6 con const myFunc = require('./myFunc');.

L'utilizzo module.exports = myFunc;invece ha risolto il problema.


0

Questo errore può essere causato quando si richiede un valore da qualcosa e si mette una parentesi alla fine, come se fosse una chiamata di funzione, ma il valore viene recuperato correttamente senza terminare le parentesi. Ad esempio, se ciò a cui stai accedendo è una proprietà "get" in Typescript.

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

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

private get SuperCoolNumber(): number {
    let response = 42;
    return response;
};
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.