How do you type a component's props in React with TypeScript?
Show answer — try answering out loud first
I define a type or interface with the shape of the props and apply it directly to the component's parameter. Optional props take ? and I give them a default value when destructuring. React.FC is no longer recommended.
Props are your component's "contract": what data it needs to work. TypeScript lets you write that contract explicitly, and in return it warns you if someone uses the component wrong (missing a prop, passing a string where a number was expected, etc.).
The key points:
- You define a
type(orinterface, both work) with the nameComponentNamePropsby convention. - You apply it to the component's parameter:
function Boton({ texto }: BotonProps). - Optional props are marked with
?. If you want a default value, you assign it when destructuring:{ color = "azul" }. - Functions that arrive via props are also typed:
onGuardar: (id: number) => voidsays "you pass me a function that receives a number and returns nothing". React.FCwas popular, but today it's not recommended: it used to injectchildreneven if you didn't use it and it complicates generics. Typing the parameter directly is simpler and more explicit.
// The component's contract: what it receives and of what type
type BotonGuardarProps = {
texto: string; // required
id: number; // required
deshabilitado?: boolean; // optional (may not be provided)
color?: "azul" | "rojo"; // optional, with limited values
onGuardar: (id: number) => void; // function that receives a number
};
// Default values directly in the destructuring
function BotonGuardar({
texto,
id,
deshabilitado = false,
color = "azul",
onGuardar,
}: BotonGuardarProps) {
return (
<button
disabled={deshabilitado}
className={`boton-${color}`}
onClick={() => onGuardar(id)}
>
{texto}
</button>
);
}
// Correct usage
// <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'
A junior often types the component with React.FC out of habit:
// It works, but it's no longer recommended
const Boton: React.FC<BotonProps> = ({ texto }) => {
return <button>{texto}</button>;
};
The problem: in older versions React.FC added implicit children (you accepted children without wanting to) and today it still gets in the way with generic components. The fix is to type the parameter directly:
function Boton({ texto }: BotonProps) {
return <button>{texto}</button>;
}
Same result, less magic, clearer.
"I type props with a
typeorinterfacethat I apply directly to the component's parameter, not withReact.FC, because that approach injected implicitchildrenand complicates generics. I mark optional props with?and give them a default value when destructuring. When a prop is a function, I type it too, for exampleonGuardar: (id: number) => void, so TypeScript warns me if someone uses the component wrong."
Create a Saludo component that receives nombre (string, required) and formal (boolean, optional, default false). If formal is true, it shows "Buenos días, {nombre}"; otherwise, "Hola, {nombre}".
See solution
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