web-dev-qa-db-fra.com

Erreur: impossible d'appeler une expression dont le type manque de signature d'appel

Je suis nouveau à TypeScript, et j'ai deux classes. Dans la classe des parents, j'ai:

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

Dans la classe enfant, j'ai:

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

ShowMore et ShowLess m'indiquent l'erreur "Impossible d'appeler une expression dont le type manque de signature d'appel".

Mais la fonction que setProp renvoie A-T-ELLE une signature d'appel, je pense? Je pense que je comprends mal quelque chose d’important à propos de la saisie de fonctions, mais je ne sais pas ce que c’est.

Merci!

96
Justin

La fonction qu'il renvoie a une signature d'appel, mais vous avez dit à TypeScript de l'ignorer complètement en ajoutant : any dans sa signature.

Ne fais pas ça.

61
SLaks

"Impossible d'appeler une expression dont le type ne comporte pas de signature d'appel."

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

Vous avez public toggleBody: string;. Vous ne pouvez pas appeler une fonction string. D'où des erreurs sur: this.toggleBody(true); et this.toggleBody(false);

33
basarat

Décomposons ceci:

  1. L'erreur dit

    Impossible d'appeler une expression dont le type ne contient pas de signature d'appel.

  2. Le code:

Le problème est dans cette ligne public toggleBody: string; &

c'est par rapport à ces lignes:

...
return this.toggleBody(true);
...
return this.toggleBody(false);
  1. Le résultat:

Votre dicton toggleBody est un string mais ensuite vous le traitez comme quelque chose qui a un call signature (c'est-à-dire la structure de quelque chose qui peut s'appeler: lambdas, proc, fonctions, méthodes, etc. Dans JS, il suffit de fonctionner tho.). Vous devez modifier la déclaration pour qu'elle soit public toggleBody: (arg: boolean) => boolean;.

Détails supplémentaires:

"invoquer" signifie que vous appelez ou appliquez une fonction.

"une expression" en Javascript est fondamentalement quelque chose qui produit une valeur, donc this.toggleBody() compte comme une expression.

"type" est déclaré sur cette ligne public toggleBody: string

"manque une signature d'appel" c'est parce que vous essayez d'appeler quelque chose this.toggleBody() qui n'a pas de signature (c'est-à-dire la structure de quelque chose qui peut être appelé: lambdas, proc, fonctions, méthodes, etc.) qui peut être appelé. Vous avez dit que this.toggleBody est quelque chose qui agit comme une chaîne.

En d'autres termes, l'erreur dit

Impossible d'appeler une expression (this.toggleBody) car son type (: string) n'a pas de signature d'appel (bc il a une signature de chaîne).

19
Taysky

Je pense que ce que tu veux c'est:

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

Le changement important est dans setProp (c'est-à-dire makePropSetter dans le nouveau code). Ce que vous faites réellement, c’est à dire: c’est une fonction qui, munie d’un nom de propriété, renvoie une fonction qui vous permet de modifier cette propriété.

Le <T> sur makePropSetter vous permet de verrouiller cette fonction sur un type spécifique. Le <boolean> dans le constructeur de la sous-classe est en fait facultatif. Puisque vous assignez à toggleBody, et que le type est déjà spécifié, le compilateur TS pourra le résoudre lui-même.

Ensuite, dans votre sous-classe, vous appelez cette fonction, et le type de retour est maintenant correctement compris comme une fonction avec une signature spécifique. Naturellement, vous aurez besoin que toggleBody respecte la même signature.

6
Andrew Miner

Cela signifie que vous essayez d'appeler quelque chose qui n'est pas une fonction

const foo = 'string'
foo() // error
2
Gunar Gessner

Ajoutez un type à votre variable, puis revenez.

Par exemple:

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

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

=> La partie importante ajoute la chaîne [] type etc:

0
Afshin Ghazi

J'ai eu le même message d'erreur. Dans mon cas, j'avais mélangé par inadvertance la syntaxe ES6 export default function myFunc avec const myFunc = require('./myFunc');.

Utiliser module.exports = myFunc; à la place a résolu le problème.

0
Charlie Weems