0Pricing
TypeScript Academy · Leçon

Modéliser des machines à états

Représenter des états finis avec des unions discriminées.

Modéliser des machines à états est une leçon TypeScript Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage TypeScript Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours TypeScript Academy comprend 4 leçons au total.

Les états comme union discriminée

Les interfaces utilisateur et les flux asynchrones possèdent des états distincts : inactif, chargement, réussite et erreur. Les modéliser comme une union discriminée permet à chaque état de contenir exactement les données dont il a besoin.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

const s: State = { status: "idle" };
console.log(s.status);

Données associées à chaque état

Seul l'état success possède des data ; seul l'état error possède un message. Les états inactif et chargement ne contiennent rien de plus, ce qui empêche la propagation de données obsolètes entre les états.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: number[] }
  | { status: "error"; message: string };

const ok: State = { status: "success", data: [1, 2, 3] };
console.log(ok.status, "data" in ok ? ok.data : null);

Afficher chaque état

Une fonction qui sélectionne selon status peut afficher la sortie appropriée pour chaque état, les champs des membres n'étant disponibles que là où ils existent.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function view(s: State): string {
  switch (s.status) {
    case "idle": return "Ready";
    case "loading": return "Loading...";
    case "success": return "Got: " + s.data;
    case "error": return "Failed: " + s.message;
  }
}
console.log(view({ status: "success", data: "users" }));

Définir les transitions

Une machine à états passe d'un état à l'autre au moyen de transitions. Une fonction de transition reçoit l'état actuel et un événement, puis renvoie l'état suivant.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

function start(s: State): State {
  if (s.status === "idle") return { status: "loading" };
  return s;
}
console.log(start({ status: "idle" }).status);

Modéliser également les événements

Les événements eux-mêmes peuvent former une union discriminée. Chaque type d'événement déclenche une transition précise.

type Event =
  | { type: "FETCH" }
  | { type: "RESOLVE"; data: string }
  | { type: "REJECT"; message: string };

const e: Event = { type: "RESOLVE", data: "ok" };
console.log(e.type);

Une fonction de transition complète

Combinez les unions d'états et d'événements dans un seul réducteur. Utiliser des sélections selon les deux rend chaque transition explicite et sûre du point de vue des types.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };
type Event =
  | { type: "FETCH" }
  | { type: "RESOLVE"; data: string }
  | { type: "REJECT"; message: string };

function reduce(s: State, e: Event): State {
  if (e.type === "FETCH") return { status: "loading" };
  if (e.type === "RESOLVE") return { status: "success", data: e.data };
  return { status: "error", message: e.message };
}
console.log(reduce({ status: "idle" }, { type: "FETCH" }).status);

Les états illégaux sont impossibles à représenter

Vous ne pouvez pas avoir data et un error message en même temps. La conception par union interdit par construction les états contradictoires.

type State =
  | { status: "success"; data: string }
  | { status: "error"; message: string };

// const bad: State = { status: "success", data: "x", message: "y" };
// Allowed extra props would be flagged in strict object checks.
console.log("no contradictory states");

Protéger les transitions invalides

Vous pouvez ignorer les événements qui ne s'appliquent pas à l'état actuel, afin de conserver une machine cohérente plutôt que de provoquer un plantage.

type State = { status: "idle" } | { status: "loading" };
type Event = { type: "FETCH" } | { type: "CANCEL" };

function reduce(s: State, e: Event): State {
  if (s.status === "loading" && e.type === "CANCEL") return { status: "idle" };
  if (s.status === "idle" && e.type === "FETCH") return { status: "loading" };
  return s; // ignore invalid combos
}
console.log(reduce({ status: "loading" }, { type: "CANCEL" }).status);

Ajouter l'exhaustivité

Associez le réducteur à assertNever afin que l'ajout d'un nouvel état ou événement fasse apparaître chaque endroit à mettre à jour.

function assertNever(x: never): never { throw new Error("unhandled"); }
type State = { status: "idle" } | { status: "loading" } | { status: "done"; data: string };

function view(s: State): string {
  switch (s.status) {
    case "idle": return "idle";
    case "loading": return "loading";
    case "done": return s.data;
    default: return assertNever(s);
  }
}
console.log(view({ status: "done", data: "ok" }));

États initial et finaux

Désignez un état de départ clair (souvent idle) et des états terminaux (success ou error). Cela documente le cycle de vie de la machine.

type State =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: string }
  | { status: "error"; message: string };

const initial: State = { status: "idle" };
console.log("Start:", initial.status);

Une petite machine à états complète

Voici le cycle complet : commencer à l'état inactif, lancer la récupération pour passer au chargement, puis résoudre vers la réussite. Les types garantissent la cohérence de chaque étape.

type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
type Event = { type: "FETCH" } | { type: "RESOLVE"; data: string };

function reduce(s: State, e: Event): State {
  if (e.type === "FETCH") return { status: "loading" };
  return { status: "success", data: e.data };
}
let st: State = { status: "idle" };
st = reduce(st, { type: "FETCH" });
st = reduce(st, { type: "RESOLVE", data: "hi" });
console.log(st.status, st.status === "success" ? st.data : "");

Vérification rapide : machines à états

Vérifiez votre compréhension de la modélisation des machines à états.

Récapitulatif : modéliser des machines à états

Vous avez modélisé les états inactif/chargement/réussite/erreur comme une union discriminée, écrit des transitions sûres du point de vue des types sur des unions d'états et d'événements, et utilisé l'exhaustivité pour maintenir la fiabilité de la machine à mesure qu'elle évolue.

type State = { status: "idle" } | { status: "loading" } | { status: "success"; data: string };
const s: State = { status: "success", data: "done" };
console.log(s.status === "success" ? s.data : "");

Questions Fréquemment Posées

La leçon « Modéliser des machines à états » est-elle gratuite ?

Oui — le texte complet de « Modéliser des machines à états » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours TypeScript Academy, passe à CoddyKit PRO. Le cours TypeScript Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Modéliser des machines à états » ?

Représenter des états finis avec des unions discriminées. Tu pratiques TypeScript Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer TypeScript Academy ?

Aucune expérience préalable n'est requise. TypeScript Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Modéliser des machines à états » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon TypeScript Academy ?

Oui. Chaque leçon TypeScript Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Construire des unions discriminées
  2. Restreindre selon le discriminant
  3. Vérifier l’exhaustivité avec never
  4. Modéliser des machines à états
← Retour à TypeScript Academy