
Typer les composants fonctionnels (`React.FC`) et les props (`interface`, `type`)
Apprenez à définir et utiliser des types pour les props de vos composants fonctionnels React avec TypeScript, en utilisant `interface`, `type` et (historiquement) `React.FC`.
Définir le contrat : L'importance de typer les Props
Les props sont le principal moyen de communication entre les composants React parents et enfants. Elles constituent le "contrat" d'un composant : les données qu'il s'attend à recevoir pour fonctionner correctement. En JavaScript simple, il n'y a aucune garantie que les props passées correspondent à ce que le composant attend, ce qui peut entraîner des erreurs à l'exécution si une prop est manquante, mal nommée ou du mauvais type.
TypeScript résout ce problème en nous permettant de définir précisément la "forme" (shape) attendue des props d'un composant. En typant les props, nous bénéficions de :
- Validation statique : TypeScript vérifie au moment de la compilation que les bonnes props, avec les bons types, sont passées lors de l'utilisation du composant.
- Autocomplétion : L'éditeur de code peut suggérer les noms de props disponibles et leurs types.
- Auto-documentation : La définition des types sert de documentation claire sur la manière d'utiliser le composant.
- Refactorisation plus sûre : Si vous renommez ou modifiez une prop, TypeScript vous aidera à trouver tous les endroits où elle est utilisée.
Définir la forme des Props : `interface` vs `type`
TypeScript offre deux mots-clés principaux pour définir la structure d'un objet, comme l'objet `props` : `interface` et `type` (alias de type).
interface: Traditionnellement utilisé pour définir la forme des objets ou des classes. Les interfaces peuvent être étendues (héritage) et fusionnées (declaration merging).interface UserProfileProps { userId: number; name: string; isActive: boolean; tags?: string[]; // Prop optionnelle (tableau de chaînes) }type: Plus flexible, `type` peut définir non seulement des formes d'objets, mais aussi des types primitifs, des unions, des intersections, des tuples, etc. Les alias de type ne peuvent pas être étendus ou fusionnés de la même manière que les interfaces.type UserProfileProps = { userId: number; name: string; isActive: boolean; tags?: string[]; // Prop optionnelle };
Lequel choisir ? Pour définir la forme des props, les deux fonctionnent très bien et le choix relève souvent de la préférence personnelle ou des conventions de l'équipe. Les interfaces sont parfois préférées pour leur capacité d'extension et de fusion, tandis que les types sont plus polyvalents pour d'autres usages de TypeScript. La tendance actuelle penche légèrement vers l'utilisation de `type` pour sa simplicité et sa cohérence avec d'autres définitions de types, mais les interfaces restent très courantes et valides.
Pour définir une prop optionnelle, on ajoute un point d'interrogation ? avant les deux-points (ex: tags?: string[]). Pour typer les enfants passés au composant, on peut ajouter explicitement `children?: React.ReactNode;` à la définition des props.
Typer le composant fonctionnel : `React.FC` (historique) vs Typage direct
Une fois la forme des props définie (avec `interface` ou `type`), il faut l'appliquer au composant fonctionnel. Il existe principalement deux approches :
- 1. Utilisation de `React.FC` (ou `React.FunctionComponent`) : C'est un type générique fourni par React qui type un composant fonctionnel. On lui passe le type des props en argument générique.
import React from 'react'; interface GreetingProps { name: string; } // Utilisation de React.FC const Greeting: React.FC= ({ name }) => { return Hello, {name}!
; }; export default Greeting;React.FCprésente quelques caractéristiques :- Il type correctement les props selon le type fourni.
- Il ajoute implicitement la prop `children: React.ReactNode` au type des props, même si vous ne l'avez pas définie.
- Il fournit le typage pour d'éventuelles propriétés statiques comme `displayName` ou `defaultProps` (bien que `defaultProps` soit moins utilisé avec les fonctions fléchées).
- 2. Typage direct des Props (Approche recommandée aujourd'hui) : Cette approche consiste à typer directement le paramètre `props` de la fonction du composant, sans utiliser `React.FC`.
import React from 'react'; interface GreetingProps { name: string; // Si on veut des enfants, on les ajoute explicitement : // children?: React.ReactNode; } // Typage direct des props const Greeting = ({ name }: GreetingProps) => { // Ou : const Greeting = (props: GreetingProps) => { const { name } = props; ... } returnHello, {name}!
; }; export default Greeting;
Pourquoi l'approche directe est-elle souvent préférée ?
- Explicité pour `children` : Elle n'ajoute pas `children` implicitement. Si votre composant accepte des enfants, vous devez l'ajouter explicitement à votre type/interface de props, ce qui rend le contrat du composant plus clair.
- Syntaxe plus simple : Certains développeurs trouvent la syntaxe sans `React.FC` plus directe et moins verbeuse.
- Meilleure compatibilité historique : `React.FC` a eu quelques problèmes par le passé avec `defaultProps` et les composants génériques, bien que beaucoup aient été résolus. L'approche directe est souvent considérée comme plus simple et moins sujette à ces subtilités.
La plupart des guides et des bases de code modernes tendent à favoriser le typage direct des props plutôt que `React.FC`.
Exemple complet (Typage direct recommandé)
Voici un exemple plus complet utilisant le typage direct avec une interface, incluant des props optionnelles et `children`.
import React, { ReactNode } from 'react';
// 1. Définir la forme des props avec interface ou type
interface CardProps {
title: string;
className?: string; // Optionnelle
children: ReactNode; // Enfants explicitement requis
}
// 2. Typer directement les props du composant
const Card = ({ title, className, children }: CardProps) => {
// Utiliser une valeur par défaut pour la prop optionnelle si nécessaire
const cardClassName = `card ${className || ''}`.trim();
return (
{title}
{children}
);
};
export default Card;
// --- Utilisation du composant ---
//
// Contenu de la carte.
//
// Erreur TypeScript si title ou children est manquant
// Erreur TypeScript si className est d'un autre type que string | undefinedTypeScript vérifiera que `title` et `children` sont bien fournis lors de l'utilisation de `
Conclusion : Des composants plus sûrs et mieux documentés
Typer les props de vos composants fonctionnels React avec TypeScript est une pratique fondamentale pour améliorer la robustesse et la maintenabilité de votre code. En utilisant `interface` ou `type` pour définir la structure attendue des props et en appliquant ce type directement aux paramètres de votre composant (plutôt qu'en utilisant `React.FC`), vous créez des contrats clairs, bénéficiez d'une validation statique puissante et améliorez considérablement l'expérience de développement grâce à une meilleure autocomplétion et une documentation intégrée.