Skip to content
rocambille edited this page Apr 20, 2026 · 12 revisions

Résumé : La cohérence du typage est essentielle pour assurer la robustesse et la fiabilité du code. StartER s'appuie sur TypeScript pour garantir cette cohérence de bout en bout : du client (React) au serveur (Express). Cette page présente deux techniques fondamentales de typage utilisées dans le framework.

Le rôle de TypeScript

StartER utilise TypeScript pour garantir un contrat strict et partagé entre votre base de données, votre API, et vos composants.

Implémentation dans StartER

Types partagés : src/types/index.d.ts

Le fichier src/types/index.d.ts constitue le point central de définition des types partagés entre toutes les parties de l'application. Il fournit un ensemble de types qui sont accessibles globalement sans avoir besoin d'imports explicites.

type Item = {
  id: number;
  title: string;
  user_id: number;
};

type User = {
  id: number;
  email: string;
  name: string;
};

Les types définis ici sont automatiquement disponibles dans tout le code, sans import.

Dans les composants React, ces types sont utilisés directement. Par exemple, dans src/react/components/item/ItemList.tsx :

const items = use<Item[]>(cache("/api/items"));

Ici, Item[] indique que la variable items contient un tableau d'objets conformes au type Item.

De même, dans les modules Express, ces types sont utilisés pour garantir la cohérence. Par exemple, dans src/express/modules/item/itemRepository.ts :

async readAll(limit: number, offset: number) {
  // ...

  return rows.map<Item>(({ id, title, user_id }) => ({ id, title, user_id }));
}

Le même type Item est utilisé à la fois dans Express et React, garantissant une cohérence parfaite entre le backend et le frontend.

Fusion de déclaration pour l'interface Request d'Express

Les interfaces dans TypeScript sont ouvertes. Si une interface est définie avec le nom d'une interface existante, ses propriétés s'ajoutent à l'original. Cette capacité, appelée declaration merging, permet d'ajouter des propriétés à une interface existante sans la redéfinir entièrement. StartER exploite cette technique pour enrichir l'interface Request d'Express avec des données spécifiques à chaque module.

Chaque module Express qui ajoute une propriété à l'objet Request le fait via un bloc declare global. Par exemple, dans src/express/modules/item/itemParamConverter.ts :

declare global {
  namespace Express {
    interface Request {
      item: Item;
    }
  }
}

Après cette déclaration, TypeScript reconnaît req.item comme une propriété valide de type Item sur tous les objets Request d'Express dans l'application.

req.item = item;  // OK: req.item exists

Ainsi, chaque module étend Request avec ce dont il a besoin, avec un effet de cascade sur le reste du projet. L'IDE et le compilateur TypeScript reconnaissent les propriétés ajoutées comme légitimes.

Bonnes pratiques et cas d'usage

  1. Gardez les types communs dans index.d.ts : ce sont ceux partagés entre Express et React. Cela évite la duplication et garantit que le frontend et le backend partagent le même contrat de données.
  2. Une déclaration = une responsabilité : chaque module doit étendre Request uniquement pour ses besoins. Si un module étend Request avec des propriétés qui ne le concernent pas, les types deviennent imprévisibles pour les autres modules.
  3. Nommez les propriétés de manière cohérente (par exemple req.item, req.user...) : des conventions de nommage facilitent la lecture du code et réduisent les erreurs de saisie (autocomplétion fiable).
  4. Évitez les collisions de noms entre modules : deux modules utilisant le même nom de propriété sur Request produiraient un conflit de types silencieux.
  5. Documentez pourquoi une propriété est ajoutée : le declare global est invisible dans le fichier qui l'utilise, donc un commentaire expliquant le besoin aide le futur contributeur (souvent vous-même).

Voir aussi

Clone this wiki locally