Journal

satisfies, const type parameters et narrowing avancé

Journal du lundi 24 août 2026, généré le 24 août à 09:53

L'opérateur satisfies : garder l'inférence sans perdre la validation

Un piège classique en TypeScript consiste à annoter une variable avec un type trop large pour la sécuriser, au prix de la perte de l'inférence fine. L'opérateur satisfies (depuis TS 4.9) résout ce dilemme : il vérifie qu'une valeur respecte un type sans l'élargir.

type Couleur = "red" | "green" | "blue";

const palette = {
  primaire: "blue",
  secondaire: "green",
} satisfies Record<string, Couleur>;

// palette.primaire est inféré comme "blue", pas comme Couleur
palette.primaire.toUpperCase();

Avec une simple annotation : Record<string, Couleur>, chaque propriété serait typée Couleur au lieu de sa valeur littérale exacte. satisfies conserve la précision tout en garantissant que les clés respectent bien le contrat attendu, ce qui est précieux pour des objets de configuration.

const type parameters : figer l'inférence des génériques

Depuis TypeScript 5.0, on peut préfixer un paramètre générique par const pour forcer l'inférence la plus étroite possible, sans que l'appelant ait besoin d'écrire as const à chaque appel.

function creerTuple<const T extends readonly unknown[]>(items: T): T {
  return items;
}

const t = creerTuple(["fr", "en", "es"]);
// t: readonly ["fr", "en", "es"] au lieu de string[]

C'est particulièrement utile pour des API de type builder ou de routing où la précision des littéraux conditionne l'autocomplétion et la vérification en aval.

Narrowing sur les discriminated unions

Le narrowing reste le mécanisme le plus rentable au quotidien. Sur une union discriminée, TypeScript élimine automatiquement les branches impossibles dès qu'on teste le champ discriminant.

type Etat =
  | { statut: "chargement" }
  | { statut: "succes"; donnees: string[] }
  | { statut: "erreur"; message: string };

function afficher(e: Etat) {
  switch (e.statut) {
    case "succes":
      return e.donnees.join(", ");
    case "erreur":
      return e.message;
    default:
      return "...";
  }
}

Pour forcer l'exhaustivité du switch, ajoutez un cas default qui assigne e à une variable de type never : si un nouveau statut est ajouté à l'union sans être géré, la compilation échoue immédiatement plutôt que de laisser un bug silencieux.

À retenir

  • satisfies valide sans élargir : à privilégier sur les objets de configuration littéraux.
  • const type parameters évite les as const répétés côté appelant.
  • Le narrowing exhaustif via never transforme les oublis de cas en erreurs de compilation.