Types - rocambille/start-express-react GitHub Wiki
La cohérence de typage est essentielle pour assurer la robustesse et la fiabilité du code. StartER utilise TypeScript pour apporter cette cohérence à travers tout le code, que ce soit du côté client (React) ou serveur (Express). Cette page présente deux techniques de typage fondamentales dans notre framework.
src/types/index.d.ts
Déclarations communes dans 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 Credentials = {
email: string;
password: string;
};
type Item = {
id: number;
title: string;
user_id: number;
};
type User = {
id: number;
email: string;
};
type UserWithPassword = User & {
password: string;
};
Les types déclarés dans ce fichier sont disponibles partout dans l'application sans nécessiter d'imports.
Dans les composants React, ces types sont utilisés directement. Par exemple, dans src/react/components/ItemContext.tsx
:
const items = use(cache("/api/items")) as 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() {
// ...
return rows as Item[];
}
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 : c'est la fusion de déclaration (declaration merging). Dans StartER, cette technique est utilisée pour enrichir l'interface Request
d'Express avec des propriétés spécifiques à nos modules.
Chaque module Express qui a besoin d'ajouter une propriété personnalisée à l'objet Request
déclare cette extension via 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
De cette manière, chaque module déclare uniquement les extensions dont il a besoin. L'IDE et le compilateur TypeScript reconnaissent les propriétés ajoutées comme légitimes.
Bonnes pratiques
-
Gardez les types centraux dans
index.d.ts
: Les types qui sont utilisés par Express et React doivent être définis dans ce fichier. -
Une déclaration par propriété : Chaque extension de l'interface
Request
devrait être faite dans le module qui la concerne. -
Nommage cohérent : Les propriétés ajoutées à
Request
devraient suivre une convention de nommage cohérente. -
Évitez les collisions : Assurez-vous que différents modules n'utilisent pas le même nom de propriété.
-
Documentez l'intention : Ajoutez des commentaires expliquant pourquoi une propriété est ajoutée à
Request
.
La combinaison de ces deux techniques (la centralisation des types communs et l'extension d'interfaces existantes via la fusion de déclaration) permet de maintenir un système de typage robuste et cohérent à travers tout le framework.