← Retour au programme
Module 05

TypeScript et APIs : écrire du code fiable

Sécurisez vos données avec le typage statique, puis apprenez à communiquer avec des services externes.

TypeScript ajoute un système de types puissant à JavaScript qui détecte les erreurs avant même l'exécution de votre code. Ce module vous enseigne à typer vos variables, fonctions et structures de données, puis à communiquer avec des services externes via les APIs REST. À la fin du module, vous serez capable d'écrire du code robuste et maintenable qui interagit avec le monde extérieur.

Module suivant →

Philosophie

Le typage statique est votre meilleur ami pour les projets d'envergure. Chaque annotation de type est une documentation vivante qui protège votre code contre les erreurs silencieuses.

Prérequis & Outils

  • JavaScript fondamental
  • DOM et événements
TypeScriptFetch APIPromises

Objectifs du module

  • Comprendre les types primitifs et annoter des variables et des fonctions
  • Créer des interfaces et des types personnalisés pour modéliser vos données
  • Maîtriser les génériques, les unions et les types utilitaires
  • Appeler des APIs REST avec fetch et gérer les réponses de manière typée
  • Gérer l'asynchrone avec async/await et les Promises typées

Ressource complémentaire

TypeScript pour les débutants — Cours complet

Ressource complémentaire pour découvrir TypeScript à votre rythme.

Contenu du module

Progression pas à pas.

Chaque leçon s'appuie sur la précédente avec un rythme pensé pour laisser de l'espace à la compréhension, à la pratique et à la révision.

Leçon 1

Types primitifs et annotations

Comprendre le système de types de TypeScript, annoter des variables et des fonctions, et laisser l'inférence travailler pour vous.

TypeScript est un sur-ensemble de JavaScript : tout code JavaScript valide est aussi du TypeScript valide. La différence fondamentale est l'ajout d'un système de types statiques. Cela signifie que les erreurs de type sont détectées au moment de la compilation (avant l'exécution), et non au moment de l'exécution (quand il est trop tard). Les types primitifs fondamentaux sont : string (texte), number (entiers et décimaux), boolean (true ou false), null, undefined, et void (absence de valeur de retour). Pour annoter une variable, on ajoute : type après son nom : let age: number = 25. Si vous tentez ensuite d'écrire age = "vingt-cinq", TypeScript signale l'erreur immédiatement dans votre éditeur.

L'inférence de type est l'une des fonctionnalités les plus pratiques de TypeScript : le compilateur déduit automatiquement le type d'une variable à partir de sa valeur initiale. Quand vous écrivez let message = "Bonjour", TypeScript sait que message est de type string sans que vous ayez besoin de l'écrire. En pratique, vous n'annotez explicitement que lorsque l'inférence ne suffit pas : paramètres de fonctions, valeurs de retour complexes, ou variables déclarées sans valeur initiale. Cette approche vous donne la sécurité du typage sans la lourdeur d'annoter chaque ligne.

Les fonctions en TypeScript se typent en annotant leurs paramètres et leur valeur de retour. Par exemple : function calculerTTC(prixHT: number, taux: number): number indique clairement que la fonction prend deux nombres et retourne un nombre. Les fonctions fléchées suivent la même logique : const doubler = (n: number): number => n * 2. TypeScript supporte aussi les paramètres optionnels avec ? (function saluer(nom: string, titre?: string)) et les valeurs par défaut (function saluer(nom: string, titre: string = "M.")). Le type void indique qu'une fonction ne retourne rien, tandis que never indique une fonction qui ne termine jamais (comme une fonction qui lance toujours une erreur).

Fonction typée avec paramètre optionnel et valeur par défaut.typescript
function calculerPrix(
  prixHT: number,
  taux: number = 0.20,
  remise?: number
): number {
  let total = prixHT * (1 + taux);
  if (remise) {
    total -= total * remise;
  }
  return Math.round(total * 100) / 100;
}

const prix1 = calculerPrix(100);           // 120
const prix2 = calculerPrix(100, 0.10);     // 110
const prix3 = calculerPrix(100, 0.20, 0.15); // 102

Exercice pratique

Convertisseur de température typé

Créez deux fonctions typées : celsiusVsFahrenheit(c) qui convertit des Celsius en Fahrenheit, et fahrenheitVersCelsius(f) qui fait l'inverse. Les deux fonctions prennent un number et retournent un number.

  1. Déclarez celsiusVersFahrenheit avec le paramètre c: number et le retour : number.
  2. Implémentez la formule : (c * 9/5) + 32.
  3. Déclarez fahrenheitVersCelsius avec le paramètre f: number et le retour : number.
  4. Implémentez la formule : (f - 32) * 5/9. Testez avec des valeurs connues (0°C = 32°F, 100°C = 212°F).

Les deux fonctions sont correctement typées et retournent les bonnes valeurs. 0°C → 32°F et 212°F → 100°C.

Leçon 2

Interfaces, types et structures de données

Modéliser des données complexes avec des interfaces et des types personnalisés, et maîtriser les unions, intersections et génériques.

En JavaScript, les objets sont omniprésents mais leur structure est implicite : rien ne garantit qu'un objet utilisateur contient bien un champ email. TypeScript résout ce problème avec les interfaces. Une interface décrit la forme exacte d'un objet : interface Utilisateur { nom: string; email: string; age: number; }. Ensuite, toute variable typée Utilisateur doit respecter cette structure — ajouter un champ inconnu ou oublier un champ requis provoque une erreur immédiate. Les propriétés optionnelles se déclarent avec ? : adresse?: string. Les interfaces sont ouvertes (on peut les étendre) et se combinent avec extends : interface Admin extends Utilisateur { permissions: string[]; }.

Le mot-clé type est une alternative aux interfaces qui offre plus de flexibilité. Les types unions (|) permettent d'accepter plusieurs types : type Statut = "actif" | "inactif" | "suspendu" restreint la valeur à ces trois chaînes exactes — on parle de types littéraux. Les types intersections (&) combinent plusieurs types : type AdminComplet = Utilisateur & { permissions: string[] }. Les tableaux se typent avec type[] ou Array<type> : const notes: number[] = [15, 18, 12]. Les tuples sont des tableaux de taille fixe avec des types par position : type Coordonnees = [number, number]. Choisissez interface pour les objets et type pour les unions, les tuples et les compositions complexes.

Les génériques sont le mécanisme le plus puissant de TypeScript pour écrire du code réutilisable et typé. Un générique est un « type paramètre » : au lieu de fixer un type concret, vous laissez l'appelant le spécifier. Par exemple, function premier<T>(tableau: T[]): T retourne le premier élément d'un tableau, quel que soit son type. À l'appel, TypeScript infère T : premier([1, 2, 3]) retourne un number, premier(["a", "b"]) retourne un string. TypeScript fournit aussi des types utilitaires préconstruits : Partial<T> rend toutes les propriétés optionnelles, Required<T> les rend toutes obligatoires, Pick<T, K> extrait certaines propriétés, et Omit<T, K> en exclut. Ces outils évitent de dupliquer des interfaces similaires.

Interface Produit avec type union pour le statut et fonction générique de filtrage.typescript
interface Produit {
  id: number;
  nom: string;
  prix: number;
  statut: "disponible" | "rupture" | "promo";
  categorie: string;
}

function filtrer<T>(tableau: T[], condition: (item: T) => boolean): T[] {
  return tableau.filter(condition);
}

const produits: Produit[] = [
  { id: 1, nom: "Clavier", prix: 89, statut: "disponible", categorie: "info" },
  { id: 2, nom: "Souris", prix: 45, statut: "promo", categorie: "info" },
  { id: 3, nom: "Casque", prix: 120, statut: "rupture", categorie: "audio" },
];

const promos = filtrer(produits, (p) => p.statut === "promo");
const abordables = filtrer(produits, (p) => p.prix < 100);

Exercice pratique

Système de gestion d'étudiants typé

Créez une interface Etudiant (nom, age, notes: number[], filiere), un type union Mention, et une fonction qui calcule la moyenne et retourne l'étudiant avec sa mention.

  1. Définissez l'interface Etudiant avec les propriétés : nom (string), age (number), notes (number[]), filiere (string).
  2. Créez un type Mention = "Très bien" | "Bien" | "Assez bien" | "Passable" | "Insuffisant".
  3. Écrivez une fonction calculerMoyenne(notes: number[]): number qui retourne la moyenne.
  4. Écrivez une fonction obtenirMention(moyenne: number): Mention qui retourne la mention selon la moyenne (≥16 Très bien, ≥14 Bien, ≥12 Assez bien, ≥10 Passable, sinon Insuffisant).

L'interface Etudiant est correcte, le type Mention contient 5 valeurs littérales, la moyenne de [15, 17, 14, 18, 16] est 16 et la mention est "Très bien".

Leçon 3

APIs REST et programmation asynchrone

Appeler des APIs externes avec fetch, typer les réponses, et maîtriser async/await pour gérer les opérations asynchrones.

Une API (Application Programming Interface) REST est un service accessible via des URLs qui permet à votre application de communiquer avec des serveurs distants. Chaque URL (appelée endpoint) représente une ressource, et les méthodes HTTP déterminent l'action : GET pour lire des données, POST pour en créer, PUT pour les modifier entièrement, PATCH pour les modifier partiellement, et DELETE pour les supprimer. Par exemple, GET https://api.example.com/utilisateurs retourne la liste des utilisateurs. Les réponses sont généralement au format JSON, que TypeScript sait parfaitement typer pour garantir que vous manipulez les bonnes données.

La fonction fetch() est l'outil natif du navigateur pour appeler des APIs. Elle retourne une Promise — un objet qui représente une valeur future (la réponse du serveur arrivera plus tard). Les mots-clés async/await simplifient la gestion des Promises : async devant une fonction indique qu'elle contient des opérations asynchrones, et await « attend » le résultat d'une Promise avant de continuer. Sans async/await, il faudrait enchaîner des .then() et .catch(), ce qui devient vite illisible. En TypeScript, on type la réponse après le parsing JSON : const data: Utilisateur[] = await response.json(). Ainsi, l'autocomplétion et la vérification de types fonctionnent sur les données reçues de l'API.

La gestion des erreurs est cruciale quand on appelle des APIs : le réseau peut échouer, le serveur peut renvoyer une erreur, ou les données peuvent ne pas correspondre au format attendu. Le bloc try/catch permet de capturer ces erreurs proprement. Vérifiez toujours response.ok (qui est true pour les codes 200-299) avant de parser la réponse. En TypeScript, créez des types pour les erreurs aussi : type ApiError = { message: string; code: number }. Une bonne pratique est d'encapsuler les appels API dans des fonctions dédiées qui gèrent les erreurs et retournent des données typées. Cela centralise la logique réseau et rend le reste du code plus propre.

Appel API typé avec gestion d'erreur complète et fonction réutilisable.typescript
interface Article {
  id: number;
  title: string;
  body: string;
  userId: number;
}

async function recupererArticles(): Promise<Article[]> {
  const response = await fetch(
    "https://jsonplaceholder.typicode.com/posts?_limit=5"
  );

  if (!response.ok) {
    throw new Error(`Erreur HTTP : ${response.status}`);
  }

  const articles: Article[] = await response.json();
  return articles;
}

async function main() {
  try {
    const articles = await recupererArticles();
    articles.forEach((article) => {
      console.log(`#${article.id} — ${article.title}`);
    });
  } catch (erreur) {
    console.error("Impossible de charger les articles :", erreur);
  }
}

main();

Exercice pratique

Client API météo typé

Créez une fonction typée qui appelle une API météo (utilisez jsonplaceholder ou une API gratuite), parse la réponse dans une interface, gère les erreurs, et affiche les données de manière formatée.

  1. Définissez une interface Todo avec les propriétés : id (number), title (string), completed (boolean), userId (number).
  2. Créez une fonction async recupererTodos(): Promise<Todo[]> qui appelle https://jsonplaceholder.typicode.com/todos?_limit=10.
  3. Vérifiez response.ok et lancez une erreur si la requête échoue.
  4. Dans un bloc try/catch, appelez la fonction, filtrez les todos complétés et affichez le résultat.

La fonction récupère les todos, les filtre par statut completed, et affiche les résultats. Les erreurs réseau et HTTP sont gérées correctement.

Projet final

Dashboard météo typé avec API externe

Construisez un programme TypeScript qui interroge une API publique (JSONPlaceholder ou OpenMeteo), modélise les données avec des interfaces, affiche un résumé formaté et gère toutes les erreurs possibles. Le projet doit démontrer votre maîtrise du typage, des interfaces et de l'asynchrone.

Critères de réussite

  • Toutes les données sont modélisées avec des interfaces (au moins 3 interfaces distinctes).
  • Les appels API utilisent fetch avec async/await et retournent des Promises typées.
  • Les erreurs réseau et HTTP sont gérées avec try/catch et des messages clairs.
  • Le code utilise au moins un type union et un type utilitaire (Partial, Pick ou Omit).
  • Les fonctions sont correctement typées (paramètres et retour) et réutilisables.

Guide de réalisation

  • 1Commencez par définir vos interfaces : Utilisateur, Article, et un type Résumé qui combine les deux.
  • 2Créez une fonction générique fetchData<T>(url: string): Promise<T> pour centraliser les appels API.
  • 3Utilisez Promise.all() pour appeler plusieurs endpoints en parallèle.
  • 4Formatez l'affichage avec des fonctions dédiées qui prennent des données typées en paramètre.

Consolidez vos acquis avant de poursuivre.

Prenez le temps de revoir les concepts difficiles et de refaire les exercices qui méritent une seconde passe.