¿Cómo tipas las props de un componente en React con TypeScript?
Ver respuesta — intenta responderla en voz alta primero
Defino un type o interface con la forma de las props y lo aplico directo al parámetro del componente. Las props opcionales llevan ? y les doy un valor por defecto al destructurar. Ya no se recomienda React.FC.
Las props son el "contrato" de tu componente: qué datos necesita para funcionar. TypeScript te permite escribir ese contrato de forma explícita, y a cambio te avisa si alguien usa el componente mal (le falta una prop, le pasa un string donde iba un number, etc.).
Los puntos clave:
- Defines un
type(ointerface, ambos funcionan) con el nombreNombreDelComponentePropspor convención. - Lo aplicas al parámetro del componente:
function Boton({ texto }: BotonProps). - Las props opcionales se marcan con
?. Si quieres un valor por defecto, lo asignas al destructurar:{ color = "azul" }. - Las funciones que llegan por props también se tipan:
onGuardar: (id: number) => voiddice "me pasas una función que recibe un número y no devuelve nada". React.FCfue popular, pero hoy no se recomienda: antes inyectabachildrenaunque no lo usaras y complica los genéricos. Tipar el parámetro directo es más simple y explícito.
// El contrato del componente: qué recibe y de qué tipo
type BotonGuardarProps = {
texto: string; // obligatoria
id: number; // obligatoria
deshabilitado?: boolean; // opcional (puede no venir)
color?: "azul" | "rojo"; // opcional, con valores limitados
onGuardar: (id: number) => void; // función que recibe un número
};
// Valores por defecto directo en el destructuring
function BotonGuardar({
texto,
id,
deshabilitado = false,
color = "azul",
onGuardar,
}: BotonGuardarProps) {
return (
<button
disabled={deshabilitado}
className={`boton-${color}`}
onClick={() => onGuardar(id)}
>
{texto}
</button>
);
}
// Uso correcto
// <BotonGuardar texto="Guardar" id={7} onGuardar={(id) => console.log(id)} />
// <BotonGuardar texto="Guardar" onGuardar={...} />
// Error: Property 'id' is missing in type ...
// <BotonGuardar texto="Guardar" id="7" onGuardar={...} />
// Error: Type 'string' is not assignable to type 'number'
Un junior suele tipar el componente con React.FC por costumbre:
// Funciona, pero ya no se recomienda
const Boton: React.FC<BotonProps> = ({ texto }) => {
return <button>{texto}</button>;
};
El problema: en versiones antiguas React.FC metía children implícito (aceptabas hijos sin quererlo) y hoy sigue estorbando con componentes genéricos. La corrección es tipar el parámetro directamente:
function Boton({ texto }: BotonProps) {
return <button>{texto}</button>;
}
Mismo resultado, menos magia, más claro.
"Yo tipo las props con un
typeointerfaceque aplico directo al parámetro del componente, no conReact.FC, porque ese enfoque inyectabachildrenimplícito y complica los genéricos. Las props opcionales las marco con?y les doy valor por defecto al destructurar. Cuando una prop es una función, también la tipo, por ejemploonGuardar: (id: number) => void, y así TypeScript me avisa si alguien usa mal el componente."
Crea un componente Saludo que reciba nombre (string, obligatorio) y formal (boolean, opcional, por defecto false). Si formal es true, muestra "Buenos días, {nombre}"; si no, "Hola, {nombre}".
Ver solución
type SaludoProps = {
nombre: string;
formal?: boolean;
};
function Saludo({ nombre, formal = false }: SaludoProps) {
const mensaje = formal ? `Buenos días, ${nombre}` : `Hola, ${nombre}`;
return <p>{mensaje}</p>;
}
// <Saludo nombre="Ana" /> -> Hola, Ana
// <Saludo nombre="Ana" formal /> -> Buenos días, Ana