Introduction : Votre composant "se tait" parce qu'il ne sait pas naître
Vous codez en TypeScript avec React, tout se passe comme sur des roulettes. Et soudain — bam ! — le compilateur vous jette au visage un message mystérieux :
JSX element type 'MyComponent' does not have any construct or call signatures.Un scénario familier ? Si vous êtes débutant, cette erreur peut ressembler à une incantation venue d'un autre monde. Mais ne paniquez pas. En réalité, c'est simple : TypeScript vous dit que ce que vous essayez d'utiliser comme composant JSX n'est ni une fonction ni une classe que l'on peut "appeler" ou "construire".
Dans cet article, nous allons décortiquer cette erreur de manière simple : pourquoi elle se produit, comment la corriger, et ce que signifient ces "construct or call signatures". C'est parti — nous allons apprendre de manière amusante et avec des exemples !
Que signifient "construct or call signatures" ?
Imaginons qu'un composant JSX soit un restaurant. Vous entrez, vous vous asseyez à une table (vous passez des props) et vous attendez qu'on vous apporte à manger (return JSX). Mais si le restaurant est fermé pour rénovation ou n'existe tout simplement pas, vous ne pouvez pas passer commande.
En TypeScript, une "construct signature" est la capacité d'une classe à être appelée avec new (comme un constructeur). Une "call signature" est la capacité d'une fonction à être appelée directement. Les composants JSX dans React peuvent être soit des fonctions, soit des classes. Si TypeScript ne voit chez votre "composant" ni l'un ni l'autre, il génère une erreur.
Cas typique :
// Incorrectconst MyComponent = someObject;// <MyComponent /> — erreur !
// Correctconst MyComponent: React.FC<Props> = (props) => { return <div>Bonjour</div>;};// <MyComponent /> — fonctionneL'erreur se produit lorsque vous essayez d'utiliser dans JSX quelque chose qui n'est ni une fonction ni une classe. Par exemple, une chaîne de caractères, un nombre, un objet ou une variable non initialisée.
Top 5 des causes de l'erreur (avec exemples de code en TypeScript)
Examinons les scénarios les plus courants où vous pouvez tomber dans ce piège. Pour chaque cas, je montrerai à quoi ressemble le problème et comment le corriger.
1. Le composant est un objet, pas une fonction
Le piège le plus fréquent. Vous importez quelque chose en pensant que c'est un composant, mais c'est un simple objet contenant des données ou une configuration.
// ❌ Erreurimport userData from './userData';// userData = { name: 'Anna', age: 25 }function App() { return <userData />; // userData — objet, pas un composant !}
// ✅ Correctionimport UserCard from './UserCard';function App() { return <UserCard user={userData} />;}Comment vérifier : survolez la variable dans votre IDE. Si TypeScript affiche le type object, Record<string, any> ou quelque chose de similaire sans () => JSX.Element — ce n'est pas un composant.
2. Le composant est une chaîne de caractères ou un nombre
Par inattention, on peut parfois passer dans JSX un littéral ou une variable de type primitif.
// ❌ Erreurconst greeting = "Bonjour le monde !";function App() { return <greeting />; // greeting est une string}
// ✅ Correctionfunction App() { return <h1>{greeting}</h1>; // Utilisé comme texte, pas comme composant}3. Le composant est mal importé
Si vous utilisez export default et importez sans accolades, mais que l'export était nommé — vous obtiendrez undefined. Et undefined dans JSX provoque exactement cette erreur.
// Dans le fichier Button.tsxexport const Button = () => <button>Cliquez</button>;// export default absent !
// ❌ Erreurimport Button from './Button'; // Button = undefinedfunction App() { return <Button />;}
// ✅ Correctionimport { Button } from './Button'; // Import nommé// ou ajoutez export default dans Button.tsx