Un écran d'ordinateur affichant du code.

Comprendre et utiliser les PropTypes dans React

Publié le le

Combien de fois avez-vous passé des heures à déboguer un composant React, pour finalement découvrir qu'une prop était mal typée ou manquante ? Ce genre de bug silencieux peut vite transformer une journée productive en cauchemar de débogage.

C'est exactement là que les PropTypes entrent en jeu. Cet outil de validation vous permet de définir un "contrat" clair pour vos composants : quelles props ils acceptent, de quel type, lesquelles sont obligatoires. Résultat ? Les erreurs remontent en surface dès le développement, avant d'atteindre vos utilisateurs.

Dans cet article, nous verrons comment maîtriser les PropTypes pour écrire du code React plus robuste, pourquoi ils gardent toute leur utilité même à l'ère de TypeScript, et quelles pratiques adopter pour en tirer le maximum.

Pourquoi adopter les PropTypes ?

Imaginez pouvoir attraper vos erreurs avant même qu'elles n'atteignent le navigateur. C'est exactement ce que vous offrent les PropTypes, et bien plus encore :

Fini les bugs silencieux. Plus besoin de chercher pendant des heures pourquoi votre composant ne s'affiche pas correctement. Les PropTypes vous alertent instantanément si vous passez un string là où un nombre est attendu, ou si vous oubliez une prop critique.

Une documentation qui ne ment jamais. Contrairement aux commentaires qui finissent souvent obsolètes, les PropTypes reflètent toujours la réalité de votre code. Un coup d'œil aux PropTypes d'un composant et vous savez immédiatement comment l'utiliser.

Évolution sereine du code. Besoin de modifier l'API d'un composant ? Les PropTypes vous montrent instantanément tous les endroits qui nécessitent une mise à jour. Plus de refactoring à l'aveugle.

Et avec TypeScript ? Si vous utilisez déjà TypeScript, les PropTypes peuvent sembler redondants. Pourtant, ils gardent leur intérêt : TypeScript vérifie vos types à la compilation, mais les PropTypes vous protègent au runtime quand les données viennent d'une API externe ou d'un composant JavaScript non typé.

Installation et mise en place

Les PropTypes ne font plus partie de React depuis la version 15.5, ils vivent maintenant dans leur propre package. Une ligne de commande et c'est parti :

npm install prop-types

Ensuite, un simple import dans vos composants :

import PropTypes from 'prop-types';

Premier exemple concret

Prenons un composant utilisateur classique. Sans PropTypes, impossible de savoir quelles props il attend. Avec PropTypes, l'attendu devient plus clair:

import React from 'react';
import PropTypes from 'prop-types';

function UserCard({ name, age, isActive }) {
  return (
    <div className="user-card">
      <h3>{name}</h3>
      <p>Age: {age}</p>
      <span className={`status ${isActive ? 'active' : 'inactive'}`}>
        {isActive ? 'Online' : 'Offline'}
      </span>
    </div>
  );
}

UserCard.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  isActive: PropTypes.bool,
};

export default UserCard;

Par où commencer avec les PropTypes

Pas la peine de tout apprendre d'un coup. Voici les PropTypes que vous utiliserez le plus souvent, avec des exemples concrets :

String, function et boolean - la base

Button.propTypes = {
  children: PropTypes.string.isRequired,  // Le texte du bouton
  onClick: PropTypes.func.isRequired,     // L'action au clic
  disabled: PropTypes.bool,               // État activé/désactivé
};

Ces trois types couvrent la majorité des props que vous passerez : du texte, des fonctions de callback, et des vrais/faux.

Pour valider des objets et des listes

UserProfile.propTypes = {
  user: PropTypes.shape({
    name: PropTypes.string.isRequired,
    email: PropTypes.string.isRequired,
  }).isRequired,
  tags: PropTypes.arrayOf(PropTypes.string),
};

shape vérifie qu'un objet a bien la structure attendue. arrayOf fait pareil pour les tableaux.

Pour limiter les choix possibles

Alert.propTypes = {
  type: PropTypes.oneOf(['success', 'error', 'warning']),
  size: PropTypes.oneOf(['small', 'medium', 'large']),
};

Avec oneOf, impossible de passer autre chose que les valeurs autorisées. Si quelqu'un écrit "sucess" au lieu de "success", il le saura tout de suite.

Les règles d'or des PropTypes

Après des années de projets React, quelques patterns se dégagent pour utiliser les PropTypes efficacement :

Soyez strict sur les props critiques

Ne mettez pas isRequired partout par reflexe, mais soyez impitoyable sur les props sans lesquelles votre composant plante. Un bouton sans onClick ? Required. Un avatar sans src ? Required.

Button.propTypes = {
  onClick: PropTypes.func.isRequired,  // Le composant n'a pas de sens sans ça
  children: PropTypes.node.isRequired, // Que ferait un bouton vide ?
  variant: PropTypes.oneOf(['primary', 'secondary']), // Optionnel, on a un défaut
};

Combinez PropTypes et defaultProps intelligemment

Les defaultProps ne sont pas juste des valeurs par défaut, ils documentent aussi vos intentions. Ils disent "voici le comportement normal, mais vous pouvez le personnaliser".

function NotificationCard({ type, message, autoClose, duration }) {
  // Logique du composant...
}

NotificationCard.propTypes = {
  type: PropTypes.oneOf(['success', 'error', 'warning', 'info']),
  message: PropTypes.string.isRequired,
  autoClose: PropTypes.bool,
  duration: PropTypes.number, // en millisecondes
};

NotificationCard.defaultProps = {
  type: 'info',
  autoClose: true,
  duration: 5000,
};

Ici, impossible de se tromper : le message est obligatoire, tout le reste a des valeurs sensées par défaut. Un développeur qui découvre ce composant sait immédiatement comment l'utiliser.

Testez vos PropTypes en conditions réelles

Les PropTypes ne servent à rien s'ils ne catchent pas les vrais problèmes. Testez avec des données foireuses : objets null, arrays vides, strings au lieu de numbers. C'est là que vous verrez si vos validations tiennent la route.

PropTypes vs TypeScript

La question revient systématiquement : faut-il migrer vers TypeScript ou rester sur PropTypes ? La réponse dépend surtout de votre contexte, pas de dogmes techniques.

Quand PropTypes gardent l'avantage

Sur du legacy JavaScript. Vous avez une codebase JS existante de 50k lignes ? Les PropTypes s'ajoutent sans friction, composant par composant. TypeScript demanderait une migration massive avec risque de tout casser.

Pour des prototypes rapides. Vous testez une idée, vous itérez vite ? PropTypes donnent une validation basique sans la lourdeur de setup TypeScript. Parfait pour du jetable ou des POCs.

Validation runtime indispensable. Vos données viennent d'APIs externes non fiables ? PropTypes valident en production là où TypeScript se contente de la compilation.

Où TypeScript écrase la concurrence

Sur de gros projets. Plus de 20 développeurs, des milliers de composants ? L'autocomplétion, les refactorings automatiques et la détection d'erreurs de TypeScript deviennent indispensables.

Pour l'écosystème. Libs tierces typées, meilleure intégration IDE, outillage plus riche. Une fois qu'on y goûte, difficile de revenir en arrière.

Le compromis réaliste

Dans un projet TypeScript, gardez PropTypes sur les composants qui reçoivent des données externes (APIs, props depuis du JS legacy). Le double filet de sécurité compile-time + runtime n'est pas du luxe quand les enjeux sont importants.

interface UserCardProps {
  user: {
    id: string;
    name: string;
    email: string;
  };
  onEdit: (id: string) => void;
}

function UserCard({ user, onEdit }: UserCardProps) {
  // Composant...
}

// Double validation pour les données d'API
UserCard.propTypes = {
  user: PropTypes.shape({
    id: PropTypes.string.isRequired,
    name: PropTypes.string.isRequired,
    email: PropTypes.string.isRequired,
  }).isRequired,
  onEdit: PropTypes.func.isRequired,
};

Pour résumer

Les PropTypes ne révolutionneront pas votre façon de coder, mais ils évitent les bugs bêtes qui plombent une journée de dev. Quelques lignes de validation en plus, et vous dormez mieux la nuit en sachant que vos composants ne planteront pas à cause d'une prop foireuse.

Si vous êtes sur du JavaScript pur, adoptez-les sans hésiter. Sur TypeScript, gardez-les pour les composants exposés aux données externes. Et si vous débutez un gros projet en 2025, partez directement sur TypeScript - mais n'oubliez pas que PropTypes ont encore leur place dans l'écosystème.

L'essentiel ? Choisissez l'outil qui correspond à votre contexte, pas à la mode du moment.

Les questions qu'on se pose vraiment

J'ai déjà TypeScript, pourquoi m'embêter avec PropTypes ?

Bonne question ! TypeScript vous protège pendant que vous codez, mais PropTypes vous rattrapent quand les choses déconnent en production. Genre quand votre API renvoie null au lieu d'un objet, ou qu'un vieux composant JS passe n'importe quoi. C'est votre filet de sécurité runtime.

Comment je valide une liste d'utilisateurs avec leurs détails ?

C'est là que arrayOf et shape deviennent vos meilleurs amis :

users: PropTypes.arrayOf(
  PropTypes.shape({
    id: PropTypes.string.isRequired,
    name: PropTypes.string.isRequired,
    email: PropTypes.string,
  })
).isRequired

Ça valide que vous avez bien un tableau, avec des objets qui ont la bonne structure.

Ça va pas ralentir mon app ?

Pas du tout ! Les PropTypes ne tournent qu'en développement. Dès que vous buildez pour la production, ils disparaissent complètement. Zéro impact sur vos utilisateurs finaux.

Ça marche avec les hooks et les composants fonctionnels ?

Bien sûr ! Que votre composant soit une class, une fonction, qu'il utilise des hooks ou pas, les PropTypes s'en fichent. Ils regardent juste ce qui rentre dans votre composant, pas comment il fonctionne à l'intérieur.

C'est pas un truc du passé maintenant ?

Pas vraiment. Oui, TypeScript a le vent en poupe, mais PropTypes ont encore du sens sur plein de projets : du JavaScript legacy, des prototypes rapides, ou quand vous voulez une validation runtime en plus de TypeScript. Choisissez selon votre contexte, pas selon les tendances.

Sources et ressources complémentaires

Développeur buvant dans une tasse devant son écran avec du code affiché useEffect : Gérez les effets de bord dans vos composants React

Découvrez le hook useEffect de React : apprenez à gérer les effets de bord comme les appels API, les abonnements ou les mises à jour DOM dans vos composants.

Ecran d'ordinateur avec du code React affiché useState : La gestion d'état dans vos composants React

Implémentez la gestion d'état dans vos composants React avec le hook useState. Découvrez à quoi il sert et comment l'utiliser.

Un ordinateur portable affichant du code sur l'écran. Protéger et sécuriser les objets en JavaScript

Découvrez comment utiliser Object.freeze() et Object.seal() en JavaScript pour protéger vos objets. Apprenez à limiter les modifications grâce à ces méthodes.