Skip to content

📅 SAISON C Semaine 1 Épisode 4 - TypeScript et Architecture

📚 Notions du jour

Aujourd’hui, nous avons explorĂ© TypeScript, un sur-ensemble typĂ© de JavaScript, et revu les concepts clĂ©s de l’architecture d’API REST. Ce fĂ»t une journĂ©e d'introduction Ă  TypeScript, sa configuration, et son intĂ©gration dans une API Express.js, le tout en utilisant Prisma comme ORM pour la gestion des donnĂ©es.

Nous avons abordé :

  • TypeScript
    • IntĂ©rĂȘt et exĂ©cution
    • Types de base
  • Architecture API
    • Configuration TypeScript
    • API Express.js
    • Prisma : ORM

🔧 TypeScript : IntĂ©rĂȘt & ExĂ©cution

TypeScript est un langage open-source développé par Microsoft qui ajoute des types statiques à JavaScript. Cela permet de détecter des erreurs dÚs la phase de développement, améliorant ainsi la qualité et la maintenabilité du code.

Pourquoi utiliser TypeScript ?

  • DĂ©tection prĂ©coce des erreurs : Les types statiques permettent de capturer des erreurs avant l’exĂ©cution.
  • Meilleure maintenabilitĂ© : Le code est plus lisible et plus facile Ă  comprendre grĂące aux types.
  • AutocomplĂ©tion et documentation : Les IDE comme VSCode offrent une meilleure autocomplĂ©tion et documentation grĂące aux types.
  • CompatibilitĂ© avec JavaScript : Tout code JavaScript valide est aussi du TypeScript valide.

Exécution de TypeScript

TypeScript doit ĂȘtre compilĂ© en JavaScript avant d’ĂȘtre exĂ©cutĂ©. Cela se fait via le compilateur TypeScript (tsc).


📌 Types de Base en TypeScript

TypeScript introduit plusieurs types de base pour typer les variables, les paramĂštres de fonctions, et les retours de fonctions.

Types Primitifs

  • string : ChaĂźnes de caractĂšres.
  • number : Nombres (entiers et dĂ©cimaux).
  • boolean : Vrai ou faux.
  • null et undefined : type nullable.
  • void : pour indiquer qu'une fonction ne retourne aucune valeur.
  • any : Type gĂ©nĂ©rique (Ă  Ă©viter autant que possible).

Exemple de types primitifs :

// Variable declaration with types
let name: string = "Yoyo";
let age: number = 38;
let isActive: boolean = true;
let data: any = "This can be anything";

Types Complexes

  • Tableaux : Utilisation de Array<Type> ou Type[].
  • Objets : DĂ©finition de la structure des objets.
  • Tuples : Tableaux avec des types fixes pour chaque position.
  • ÉnumĂ©rations : DĂ©finition de valeurs nommĂ©es.

Exemple de types complexes :

// Array of strings
const fruits: string[] = ["apple", "banana", "orange"];

// Object
const user: { name: string; age: number } = { name: "Alice", age: 25 };

// Tuple
const person: [string, number] = ["Bob", 30];

// Enum
enum Color {
  Red,
  Green,
  Blue,
}
const favoriteColor: Color = Color.Green;

Interfaces et Types

Les interfaces et les types permettent de définir des structures de données réutilisables :

  • Les interfaces peut permettre des crĂ©er des types d'objets rĂ©untilisables.
  • Les types permettent de crĂ©er des types complexes rĂ©utilisables.

Exemple d’interface :

interface User {
  id: number;
  name: string;
  email: string;
  isActive?: boolean; // Optional property
}

const Role  User = { 
  id: 1,
  name: "John",
  email: "john@example.com"
};

Exemple de type :

type Fruit = 'banana' | 'apple' | 'peach';

const fruits: Fruit[] = ['banana', 'apple', 'peach'];

⚙ Configuration TypeScript

Pour utiliser TypeScript dans un projet, il est nécessaire de configurer le compilateur via un fichier tsconfig.json.

Création du fichier tsconfig.json

# Initiate TypeScript project
npm init -y

# Install TypeScript as dev dependency
npm install --save-dev typescript

# Generate tsconfig.json file
npx tsc --init

Exemple de tsconfig.json

{ 
  "compilerOptions": {
    "target": "esnext",
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "rootDir": "./",
    "outDir": "./dist",

    "forceConsistentCasingInFileNames": true,
    "rewriteRelativeImportExtensions": true,

    "strict": true,
    "erasableSyntaxOnly": true,
    "verbatimModuleSyntax": true,

    "skipLibCheck": true
  }
}

Explications des options :

  • target : Version de JavaScript cible (ES6, ES2015, etc.) -> derniĂšre version de JS.
  • module : Type de rĂ©solution cible pour les modules (ESM) .
  • moduleResolution : Type de rĂ©solution source pour les modules (ESM).
  • rootDir : Dossier racine des fichiers sources.
  • outDir : Dossier de sortie pour les fichiers compilĂ©s.
  • forceConsistentCasingInFileNames : Éviter les problĂšmes de casing dans les noms de fichier.
  • rewriteRelativeImportExtensions : Autoriser les imports avec l'extension .ts.
  • strict : Active les vĂ©rifications strictes des types.
  • erasableSyntaxOnly : Utiliser uniquement la syntaxe supportĂ©es par Node.js.
  • verbatimModuleSyntax : Avoir les imports de type via import type.
  • skipLibCheck : Ignore les vĂ©rifications des fichiers de dĂ©claration des bibliothĂšques.

🌐 API Express.js avec TypeScript

Comme on l'a dĂ©jĂ  vu Express.js est un framework Node.js qui permet de crĂ©er des API REST. L’utilisation de TypeScript avec Express.js amĂ©liore la robustesse du code.

Installation des Dépendances

# Install Express and associated types
npm install express
npm install --save-dev @types/express @types/node

Exemple d’API Express.js avec TypeScript

src/app.js
// src/app.ts
import express, { Request, Response } from 'express';

const app = express();
const PORT = process.env.PORT || 3000;

//  JSON parser Middleware
app.use(express.json());

app.get('/', (req: Request, res: Response) => {
  res.send('Hello, TypeScript with Express!');
});

// Start server
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Explications :

  • express.json() : Body parser pour rĂ©cupĂ©rer les body "application/json" dans req.body
  • Request et Response : Types pour les objets de requĂȘte et de rĂ©ponse importĂ©s du module Express.

đŸ—ƒïž Prisma : ORM pour la Gestion des DonnĂ©es

Prisma est un ORM (Object-Relational Mapping) moderne pour Node.js et TypeScript. Il permet de gérer les bases de données de maniÚre intuitive et type-safe. C'est une alternative à Sequelize que nous avions découvert en saison B.

Installation de Prisma

# Install Prisma
npm install prisma @prisma/client

# Initiate Prisma
npx prisma init

Configuration de Prisma

Le fichier prisma/schema.prisma définit le schéma de la base de données.

Exemple de schéma Prisma :

prisma/schema.prisma
generator client {
  provider = "prisma-client"
  output   = "../generated/prisma"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")  // No longer supported with Prisma new version 7
}

model User {
  id Int @id @default(autoincrement())

  firstname  String
  lastname   String
  email      String  @unique()
  password   String

  created_at DateTime @default(now())
  updated_at DateTime @default(now()) @updatedAt

  @@map("user") // Correspondence between the User model in the code and the "user" table in the database
}

Explications :

  • generator client : Configure le client Prisma.
  • datasource db : DĂ©finit la source de donnĂ©es (PostgreSQL, MySQL, etc.).
  • model User : DĂ©finit un modĂšle pour la table User.

Créer et appliquer notre premiÚre migration

npx prisma migrate dev --name init

Générer le Client Prisma

npx prisma generate

Utilisation de Prisma dans une API Express.js

src/app.ts
import express, { Request, Response } from 'express';
import { PrismaClient } from '@prisma/client';

const app = express();
const prisma = new PrismaClient();
const PORT = process.env.PORT || 3000;

app.use(express.json());

// Route to create a new user
app.post('/api/users', async (req: Request, res: Response) => {
  const { firstname, lastname, email, password } = req.body;
    const user = await prisma.user.create({
      data: { firstname, lastname, email, passwor },
    });
    res.json(user);
});

// Route to get all users
app.get('/api/users', async (req: Request, res: Response) => {
    const users = await prisma.user.findMany();
    res.json(users);
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

Explications :

  • PrismaClient : Instance pour interagir avec la base de donnĂ©es.
  • prisma.user.create() : CrĂ©e un nouvel utilisateur.
  • prisma.user.findMany() : RĂ©cupĂšre tous les utilisateurs.

💡 Ce Que J’ai Appris Aujourd’hui

  1. TypeScript est un outil puissant pour améliorer la qualité et la maintenabilité du code JavaScript.
  2. Les types de base en TypeScript permettent de définir des structures de données robustes.
  3. La configuration de TypeScript via tsconfig.json est essentielle pour adapter le compilateur aux besoins du projet.
  4. Express.js est un framework flexible pour créer des API REST, et son utilisation avec TypeScript renforce la robustesse du code.
  5. Prisma est un ORM moderne qui simplifie la gestion des bases de données et offre une intégration fluide avec TypeScript.

⌚ Challenge du jour

Pas de challenge aujourd'hui, l'occasion de revoir au calme les notions de la semaine.