Introducción: Su componente "está en silencio" porque no sabe cómo nacer
Está escribiendo en TypeScript con React, todo va sobre ruedas. Y de repente — ¡pum! — el compilador le lanza un mensaje misterioso:
JSX element type 'MyComponent' does not have any construct or call signatures.¿Le suena familiar? Si es principiante, este error puede parecer un hechizo de otro mundo. Pero no se apresure a entrar en pánico. En realidad, todo es simple: TypeScript le está diciendo que lo que intenta usar como componente JSX, en realidad no es ni una función ni una clase que se pueda "llamar" o "construir".
En este artículo analizaremos este error de forma sencilla: por qué ocurre, cómo solucionarlo y qué significan realmente esas "construct or call signatures". ¡Adelante — lo resolveremos de forma divertida y con ejemplos!
¿Qué significan "construct or call signatures"?
Imaginemos que un componente JSX es un restaurante. Usted entra, se sienta en una mesa (pasa los props) y espera a que le traigan la comida (return JSX). Pero si el restaurante está cerrado por reformas o simplemente no existe, no podrá hacer un pedido.
En TypeScript, una "construct signature" es la capacidad de una clase de ser invocada con new (como un constructor). Una "call signature" es la capacidad de una función de ser invocada directamente. Los componentes JSX en React pueden ser funciones o clases. Si TypeScript no ve en su "componente" ni una ni otra — muestra un error.
Caso típico:
// Incorrectoconst MyComponent = someObject;// <MyComponent /> — ¡error!
// Correctoconst MyComponent: React.FC<Props> = (props) => { return <div>Hola</div>;};// <MyComponent /> — funcionaEl error ocurre cuando intenta usar en JSX algo que no es una función o una clase. Por ejemplo, una cadena, un número, un objeto o una variable no inicializada.
Top 5 causas del error (con ejemplos de código en TypeScript)
Analicemos los escenarios más comunes donde puede encontrarse con este problema. Para cada caso, mostraré cómo se ve el problema y cómo solucionarlo.
1. El componente es un objeto, no una función
La trampa más popular. Importa algo pensando que es un componente, pero es un objeto común con datos o configuración.
// ❌ Errorimport userData from './userData';// userData = { name: 'Ana', age: 25 }function App() { return <userData />; // userData — ¡es un objeto, no un componente!}
// ✅ Soluciónimport UserCard from './UserCard';function App() { return <UserCard user={userData} />;}Cómo verificarlo: pase el cursor sobre la variable en su IDE. Si TypeScript muestra el tipo object, Record<string, any> o algo similar sin () => JSX.Element — no es un componente.
2. El componente es una cadena o un número
A veces, por descuido, se puede pasar a JSX un literal o una variable de tipo primitivo.
// ❌ Errorconst greeting = "¡Hola, mundo!";function App() { return <greeting />; // greeting — es string}
// ✅ Soluciónfunction App() { return <h1>{greeting}</h1>; // Lo usamos como texto, no como componente}3. El componente se importó incorrectamente
Si usa export default e importa sin llaves, pero la exportación era nombrada — obtendrá undefined. Y undefined en JSX es ese mismo error.
// En el archivo Button.tsxexport const Button = () => <button>Click</button>;// ¡export default no existe!
// ❌ Errorimport Button from './Button'; // Button = undefinedfunction App() { return <Button />;}
// ✅ Soluciónimport { Button } from './Button'; // Importación nombrada// o agregue export default en Button.tsx