Types en US - rocambille/start-express-react GitHub Wiki
Typing consistency is essential to ensure robust and reliable code. StartER uses TypeScript to bring this consistency across all code, whether on the client (React) or server (Express) side. This page introduces two fundamental typing techniques in our framework.
The src/types/index.d.ts
file is the central point for defining types shared across all parts of the application. It provides a set of types that are accessible globally without the need for explicit imports.
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;
};
The types declared in this file are available throughout the application without requiring any imports.
In React components, these types are used directly. For example, in src/react/components/ItemContext.tsx
:
const items = use(cache("/api/items")) as Item[];
Likewise, in Express modules, these types are used to ensure consistency. For example, in src/express/modules/item/itemRepository.ts
:
async readAll() {
// ...
return rows as Item[];
}
The same Item
type is used in both Express and React, ensuring perfect consistency between the backend and frontend.
Interfaces in TypeScript are open. If an interface is defined with the name of an existing interface, its properties are added to the original: this is called declaration merging. In StartER, this technique is used to enrich Express's Request interface with module-specific properties.
Each Express module that needs to add a custom property to the Request
object declares this extension via declare global
. For example, in src/express/modules/item/itemParamConverter.ts
:
declare global {
namespace Express {
interface Request {
item: Item;
}
}
}
After this declaration, TypeScript recognizes req.item
as a valid property of type Item
on all Express Request
objects in the application.
req.item = item; // OK: req.item exists
This way, each module only declares the extensions it needs. The TypeScript IDE and compiler recognize the added properties as legitimate.
-
Keep core types in
index.d.ts
: Types used by both Express and React should be defined in this file. -
One declaration per property: Each extension to the
Request
interface should be made in the module that applies to it. -
Consistent naming: Properties added to
Request
should follow a consistent naming convention. -
Avoid collisions: Ensure different modules don't use the same property name.
-
Document the intent: Add comments explaining why a property is added to
Request
.
The combination of these two techniques (centralizing common types and extending existing interfaces via declaration merging) allows us to maintain a robust and consistent typing system throughout the framework.