Mis à jour ces 90 derniers jours 11 nouvelles · 32 révisées
Option introduite en TypeScript 5.8 (28 février 2025) qui interdit toute syntaxe TypeScript nécessitant une génération de code : enum, namespace contenant du code, propriétés de paramètre de constructeur, import x = require(). Elle garantit que le fichier peut être exécuté par simple effacement des types, comme le fait Node.js (type stripping, stable en 24.12.0 et 25.2.0). La documentation Node la recommande avec verbatimModuleSyntax.
N'écrire qu'au crayon sur la copie : la gomme suffit pour retrouver le texte original.
// tsconfig.json
// { "compilerOptions": { "erasableSyntaxOnly": true, "verbatimModuleSyntax": true } }
// ❌ Refusé : nécessite du code généré
enum Statut { Actif, Inactif }
class A { constructor(private x: number) {} }
// ✅ Effaçable
const Statut = { Actif: 0, Inactif: 1 } as const;
type Statut = (typeof Statut)[keyof typeof Statut];
class B { #x: number; constructor(x: number) { this.#x = x; } }Cas d'usage : Tout projet exécuté par node fichier.ts, Bun ou Deno sans build, ou transpilé par un outil sans typechecker.
Option introduite en TypeScript 5.5 (20 juin 2024) qui exige une annotation de type explicite sur chaque export dont le type ne se déduit pas trivialement. En échange, les fichiers .d.ts peuvent être générés fichier par fichier, sans vérification de type globale, donc en parallèle et par des outils non-TS (Oxc, esbuild, SWC). Pensée pour les monorepos.
Chaque colis porte son étiquette complète : n'importe quel trieur peut le router sans ouvrir les autres colis.
// tsconfig.json : { "compilerOptions": { "isolatedDeclarations": true, "declaration": true } }
// ❌ Erreur TS9007 : le type de retour doit être annoté
export function creer(n: number) { return { id: n, tags: [] }; }
// ✅ Le .d.ts se déduit sans typechecker
export function creer(n: number): { id: number; tags: string[] } {
return { id: n, tags: [] };
}Cas d'usage : Monorepos où la génération des .d.ts est le goulot du build ; bibliothèques publiées avec un bundler Rust.
Stratégie de résolution des modules ajoutée en TypeScript 5.0 (16 mars 2023) pour les projets construits par Vite, esbuild, webpack ou Rolldown : elle comprend le champ exports et les conditions de package.json comme Node, mais tolère les imports sans extension et n'exige pas de syntaxe CommonJS. TypeScript 7.0 (8 juillet 2026) supprime les anciennes stratégies classic, node et node10 ; bundler et nodenext deviennent les deux choix courants.
Le plan de métro adapté à la ligne qu'on prend vraiment, plutôt que la carte routière nationale.
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler",
"noEmit": true,
"allowImportingTsExtensions": true
}
}Cas d'usage : Applications front bundlées : le bundler émet le JavaScript, tsc ne fait que vérifier les types.
Option introduite en TypeScript 5.0 (16 mars 2023) : les imports et exports sont conservés tels qu'écrits, et seuls ceux marqués type sont supprimés. Fini l'élision implicite des imports « probablement de type » : le code émis est prévisible, ce qui est indispensable aux transpileurs fichier par fichier et au type stripping de Node.js, qui la recommande avec erasableSyntaxOnly.
Le traducteur qui rend chaque phrase mot pour mot au lieu de décider ce qui « ne sert à rien ».
// tsconfig.json : { "compilerOptions": { "verbatimModuleSyntax": true } }
import type { Utilisateur } from './types.ts'; // effacé
import { type Role, charger } from './api.ts'; // Role effacé, charger gardé
// ❌ Erreur : Utilisateur est un type, il faut `import type`
// import { Utilisateur } from './types.ts';
export type { Utilisateur };Cas d'usage : Projets ESM modernes, bibliothèques, exécution directe par Node/Bun/Deno, builds Vite/esbuild/Oxc.
Mot-clé accessor introduit en TypeScript 4.9 pour les classes : accessor x = 1 déclare un champ privé de stockage et une paire getter/setter publique sur le prototype. Il vient de la proposition TC39 Decorators (Stage 2.7 au 27 septembre 2026), où il permet aux décorateurs d'intercepter lectures et écritures, ce qu'un champ ordinaire ne permet pas.
Une boîte aux lettres avec fente et clé : on passe toujours par l'ouverture, jamais par le fond de la boîte.
function suivi<T>(cible: ClassAccessorDecoratorTarget<any, T>,
ctx: ClassAccessorDecoratorContext) {
return {
set(this: any, v: T) {
console.log(`${String(ctx.name)} ←`, v);
cible.set.call(this, v);
},
};
}
class Compteur {
@suivi accessor valeur = 0; // get/set générés, stockage privé
}Cas d'usage : Décorateurs de réactivité, de validation ou d'observation de propriétés (frameworks, ORM).
Fichiers de déclaration (.d.ts) qui décrivent la forme de code JavaScript existant sans implémentation. Permettent a TS de typer des libs JS.
Comme un plan architectural sans les murs réels — il décrit la structure sans la construire.
// globals.d.ts
declare const API_URL: string;
declare function legacy(x: number): string;
// Utilisable partout sans importCas d'usage : Typer des bibliothèques JavaScript, des variables globales injectées ou du code legacy.
Fonction avec une signature asserts qui lance une erreur si la condition n'est pas remplie. Après l'appel, le type est narrowe pour le reste du scope.
Comme un douanier qui refuse l'entrée et arrête tout si vos papiers sont invalides — pas de retour possible.
function assertString(val: unknown): asserts val is string {
if (typeof val !== "string") throw new Error("Not string");
}
const x: unknown = getData();
assertString(x);
x.toUpperCase(); // x est string iciCas d'usage : Validation stricte en début de fonction qui narrowe les types pour tout le reste du bloc.
Utility type qui decompresse récursivement les Promise imbriquées pour obtenir le type de la valeur résolue finale.
Comme ouvrir des paquets cadeaux emboîtés jusqu'a trouver le vrai cadeau au centre.
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // number
type C = Awaited<string>; // stringCas d'usage : Obtenir le type résolu d'une fonction async ou d'une chaîne de Promises pour le typage correct.
Technique pour simuler du typage nominal en ajoutant une propriété fantôme (brand) a un type. Empêche le mélange accidentel de types structurellement identiques.
Comme des billets de différentes devises — même papier, même forme, mais on ne mélange pas des euros et des dollars.
type USD = number & { __brand: "USD" };
type EUR = number & { __brand: "EUR" };
const usd = (n: number) => n as USD;
const eur = (n: number) => n as EUR;
function pay(amount: USD) {}
pay(usd(100)); // OK
// pay(eur(100)); // ErreurCas d'usage : Distinguer des IDs, devises ou unités de mesure qui sont structurellement des strings/numbers.
Implémentation du Builder pattern avec un typage qui évolue a chaque étape. Chaque méthode retourne un type plus précis, garantissant la completude a la compilation.
Comme un formulaire multi-étapes ou chaque page deverrouille la suivante — pas de raccourci possible.
class QueryBuilder<T extends object = {}> {
select<K extends string>(col: K) {
return this as QueryBuilder<T & Record<K, true>>;
}
build(): T { return {} as T; }
}
new QueryBuilder().select("name").select("age").build();Cas d'usage : APIs fluides (query builders, form builders) ou l'ordre et la completude des appels sont critiques.
Types qui sélectionnent un type selon une condition (T extends U ? X : Y). Le mot-clé infer permet d'extraire des sous-types dans la branche true.
Comme un aiguillage ferroviaire — selon le type de train, il est dirige sur une voie ou une autre.
type Unwrap<T> = T extends Promise<infer U> ? U : T;
type A = Unwrap<Promise<string>>; // string
type B = Unwrap<number>; // numberCas d'usage : Extraire des types imbriques (retour de Promise, éléments de tableau, props de composants React).
Assertion qui empêche le widening et rend toutes les propriétés readonly et les valeurs littérâles. Transforme un objet/tableau en version profondément immutable.
Comme graver dans le marbre — une fois écrit, chaque détail est fige exactement tel quel.
const config = {
api: "https://api.com",
retries: 3
} as const;
// type: { readonly api: "https://api.com"; readonly retries: 3 }Cas d'usage : Créer des constantes avec des types littéraux exacts pour les discriminated unions et les lookups.
Modificateur const sur un paramètre générique, introduit en TypeScript 5.0 (16 mars 2023) : les arguments littéraux sont inférés comme s'ils portaient as const (tuples readonly, littéraux de chaîne), sans que l'appelant ait à l'écrire. La fonction obtient ainsi les types les plus précis possibles.
Un photographe qui capture la scène en haute définition d'office, sans que le client demande le mode RAW.
function nommer<const T extends readonly string[]>(noms: T): T { return noms; }
const a = nommer(['alice', 'bob']);
// a : readonly ['alice', 'bob'] (sans const : string[])
type Premier = (typeof a)[0]; // 'alice'
// Avant TS 5.0 : nommer(['alice', 'bob'] as const) côté appelantCas d'usage : Bibliothèques de routage, de validation ou de configuration typée qui veulent les littéraux exacts de l'appelant.
Utility type qui extrait les types des paramètrès du constructeur d'une classe sous forme de tuple.
Comme lire la notice de montage d'un meuble pour savoir quels outils sont nécessaires.
class Service {
constructor(public url: string, public timeout: number) {}
}
type Args = ConstructorParameters<typeof Service>;
// [string, number]Cas d'usage : Créer des factory functions ou des conteneurs d'injection de dépendances types.
Covariance: un sous-type peut remplacer le type parent (sortie). Contravariance: le type parent peut remplacer le sous-type (entrée). Déterminé la compatibilité des generics.
Covariance: un chien peut passer la ou un animal est attendu (du spécifique au général). Contravariance: l'inverse pour les consommateurs.
// Covariant: retour de fonction
type Getter<T> = () => T; // Dog -> Animal OK
// Contravariant: parametre de fonction
type Setter<T> = (val: T) => void; // Animal -> Dog OKCas d'usage : Comprendre pourquoi certaines assignations génériques échouent et concevoir des APIs correctement typées.
Fichiers .d.ts.map qui lient les déclarations aux sources originales. Permettent 'Go to Définition' de naviguer vers le .ts source au lieu du .d.ts.
Comme un GPS qui mène directement a l'usine au lieu de s'arrêter a la vitrine du magasin.
// tsconfig.json
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"sourceMap": true
}
}Cas d'usage : Monorepos et bibliothèques ou les développeurs doivent naviguer vers le code source des dépendances.
Mécanisme ou plusieurs déclarations du même nom sont fusionnées en une seule définition. S'applique aux interfaces, namespaces et enums.
Comme deux équipes qui construisent chacune une aile du même bâtiment — a la fin, c'est un seul édifice.
interface Box { width: number }
interface Box { height: number }
// Box = { width: number; height: number }
const b: Box = { width: 10, height: 20 };Cas d'usage : Étendre les types de bibliothèques tierces sans modifier leur code source.
Syntaxe @décorateur pour modifier ou annoter une classe et ses membres. TypeScript compile la version standard depuis la 5.0 (16 mars 2023) et les métadonnées (Symbol.metadata) depuis la 5.2, en plus des décorateurs historiques (experimentalDecorators). Côté TC39, la proposition Decorators figure au Stage 2.7 dans le tableau officiel au 27 septembre 2026 (dernière présentation : mai 2026) : elle n'est donc pas encore dans ECMAScript.
Comme un cadre autour d'un tableau — il enveloppe l'oeuvre sans la modifier, en ajoutant du contexte.
// Décorateur standard (TS 5.0+), sans experimentalDecorators
function log<T extends (...a: any[]) => any>(
cible: T, ctx: ClassMethodDecoratorContext
) {
return function (this: unknown, ...args: any[]) {
console.log(`appel ${String(ctx.name)}`);
return cible.apply(this, args);
} as T;
}
class Api {
@log salut() { return 'hi'; }
}Cas d'usage : Programmation orientée aspect (journalisation, autorisations, validation) dans Angular, NestJS ou TypeORM. Le mot-clé accessor (TS 4.9) crée un champ décorable avec getter/setter.
Depuis TypeScript 5.2, chaque décorateur standard reçoit context.metadata, un objet partagé par tous les décorateurs d'une même classe et exposé ensuite via Classe[Symbol.metadata]. Il remplace reflect-metadata pour attacher des informations (sérialisation, validation) lisibles à l'exécution. La proposition TC39 « Decorator Metadata » est au Stage 2.7 au 27 septembre 2026 ; un polyfill Symbol.metadata ??= Symbol('metadata') est requis.
Le carnet de bord agrafé au dossier de la classe, où chaque décorateur écrit sa note.
Symbol.metadata ??= Symbol('Symbol.metadata'); // polyfill
function serialisable(_: unknown, ctx: ClassFieldDecoratorContext) {
(ctx.metadata.champs ??= [] as string[]).push(String(ctx.name));
}
class Utilisateur {
@serialisable nom = '';
@serialisable email = '';
motDePasse = '';
}
Utilisateur[Symbol.metadata]!.champs; // ['nom', 'email']Cas d'usage : ORM, validation, sérialisation sélective, injection de dépendances sans reflect-metadata.
Valeur par défaut assignée a un paramètre générique, utilisée quand le type n'est pas explicitement fourni ni inferable. Similaire aux paramètrès par défaut de fonctions.
Comme la taille standard d'un vêtement — si vous ne précisez pas, on vous donne du M.
interface ApiResponse<T = unknown> {
data: T;
status: number;
}
const res: ApiResponse = { data: null, status: 200 };
const typed: ApiResponse<User> = { data: user, status: 200 };Cas d'usage : Fournir un type par défaut dans les bibliothèques pour simplifier l'usage basique tout en permettant la personalisation.
Union de types partageant une propriété commune (discriminant) qui permet a TS de distinguer chaque variante. Pattern fondamental pour modéliser des états.
Comme des colis avec une étiquette de couleur — la couleur suffit pour savoir quel traitement appliquer.
type Result =
| { status: "ok"; data: string }
| { status: "error"; message: string };
function handle(r: Result) {
if (r.status === "ok") r.data; // string
else r.message; // string
}Cas d'usage : Modéliser des états applicatifs (loading/success/error) avec exhaustivité garantie par le compilateur.
Quand un type conditionnel agit sur un paramètre générique nu (T extends U), il se distribue sur chaque membre d'une union. Chaque membre est évalué indépendamment.
Comme un tri postal — chaque lettre de la pile est examinées individuellement et envoyée dans la bonne boite.
type NoNull<T> = T extends null | undefined ? never : T;
type R = NoNull<string | null | number>;
// string | number (null elimine)Cas d'usage : Filtrer ou transformer chaque membre d'une union indépendamment (Exclude, Extract fonctionnent ainsi).
Trois façons de modéliser un ensemble fini: enum (objet runtime), const enum (inline a la compilation, efface), union de littéraux (zéro runtime). Chacune avec ses compromis.
Enum: un panneau permanent. Const enum: un post-it qu'on retire après lecture. Union: une règle orale connue de tous.
enum Dir { Up, Down } // objet JS emis
const enum Fast { A, B } // inline, pas d'objet
type Clean = "up" | "down"; // zero runtimeCas d'usage : Préférer les unions de littéraux pour la légèreté. Enum pour l'itération. Const enum pour la performance (avec précaution).
Utility type qui retire d'une union T tous les membres assignables a U. Fonctionne sur les unions de types, pas sur les propriétés d'objets.
Comme un filtre a café qui retient le marc — seul le liquide (les types voulus) passe.
type AllEvents = "click" | "focus" | "blur" | "scroll";
type UIEvents = Exclude<AllEvents, "scroll">;
// "click" | "focus" | "blur"Cas d'usage : Filtrer des unions pour créer des sous-ensembles de types (evenements, statuts, permissions).
Technique utilisant le type never pour garantir que tous les cas d'une union sont traites. Si un cas est oublie, le compilateur génère une erreur.
Comme une checklist de sécurité en aviation — chaque point doit être coche, aucun oubli n'est toléré.
type Shape = "circle" | "square";
function area(s: Shape) {
switch (s) {
case "circle": return 1;
case "square": return 2;
default: const _: never = s; return _;
}
}Cas d'usage : Garantir a la compilation que tout ajout a une union est géré partout dans le code.
Utility type qui extrait d'une union T les membres assignables a U. Inverse d'Exclude — garde uniquement les types correspondants.
Comme un aimant dans un tas de billes — il n'attrape que celles en métal.
type Mixed = string | number | boolean | null;
type Primitives = Extract<Mixed, string | number>;
// string | numberCas d'usage : Extraire les types spécifiques d'une large union pour un traitement spécialisé.
Restriction appliquée a un paramètre générique via extends pour garantir qu'il possède certaines propriétés. Limite les types acceptables.
Comme un casting de film — tout le monde peut postuler, mais il faut au minimum savoir chanter.
function getLength<T extends { length: number }>(x: T) {
return x.length;
}
getLength("hello"); // OK
getLength([1, 2]); // OK
// getLength(42); // Erreur: pas de lengthCas d'usage : Garantir qu'un générique possède les propriétés nécessaires avant de les utiliser.
Fonction paramétrée par un ou plusieurs types qui sont résolus a l'appel. Permet d'écrire du code réutilisable tout en conservant la sécurité des types.
Comme un moule a gâteau adaptable — même forme de base mais le résultat s'adapte a l'ingrédient (chocolat, vanille).
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const n = first([1, 2, 3]); // number
const s = first(["a", "b"]); // stringCas d'usage : Créer des fonctions utilitaires (map, filter, fetch wrapper) qui préservent les types d'entrée/sortie.
Capacité de TS a déduire automatiquement les paramètrès génériques a partir des arguments passes. Évite de spécifier explicitement les types a chaque appel.
Comme un traducteur qui détecte automatiquement la langue source sans qu'on lui dise.
function wrap<T>(value: T): { value: T } {
return { value };
}
const r = wrap(42); // T infere comme number
const s = wrap("hi"); // T infere comme stringCas d'usage : Concevoir des APIs génériques ergonomiques ou l'utilisateur n'a pas a spécifier les types manuellement.
Technique pour ajouter des déclarations au scope global via déclaré global dans un module. Permet d'étendre Window, globalThis ou les prototypes.
Comme un décret national qui ajoute une loi applicable partout — la modification est globale.
export {};
declare global {
interface Window {
analytics: { track(e: string): void };
}
}Cas d'usage : Déclarer des variables globales injectées (analytics, config, feature flags) avec un typage correct.
Option (incremental: true) qui sauvegarde un cache (.tsbuildinfo) pour ne recompiler que les fichiers modifies. Accélère drastiquement les rebuilds.
Comme un cuisinier qui ne recoupe que les légumes manquants au lieu de tout reprendre a zéro.
// tsconfig.json
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo"
}
}Cas d'usage : Tout projet de taille moyenne+ devrait activer l'incremental pour des temps de build réduits.
Depuis TypeScript 5.5 (20 juin 2024), le compilateur infère lui-même le prédicat de type (x is T) d'une fonction dont le corps se réduit à une vérification de type sur son paramètre. Le cas emblématique : arr.filter(x => x !== undefined) renvoie désormais T[] et non (T | undefined)[], sans annotation manuelle.
Le videur qui, en vous voyant sortir la carte d'identité, comprend tout seul ce qu'il vérifie.
const valeurs: (number | undefined)[] = [1, undefined, 3];
// TS 5.5 : inféré comme (x) => x is number
const nombres = valeurs.filter(x => x !== undefined);
nombres.map(n => n.toFixed(1)); // n: number, plus d'erreur
// Fonction nommée : signature inférée `pet is Fish`
function estPoisson(p: Fish | Bird) {
return 'swim' in p;
}Cas d'usage : Filtrage de tableaux, nettoyage de valeurs nulles, découpage d'unions sans écrire de type guard explicite.
Utility type qui extrait le type d'instance d'un constructeur de classe. Utile quand on travaille avec typeof Class.
Comme connaître le plat final en voyant la recette — le constructeur est la recette, l'instance est le plat.
class Logger { log(msg: string) {} }
type LoggerInstance = InstanceType<typeof Logger>;
function inject(cls: typeof Logger): LoggerInstance {
return new cls();
}Cas d'usage : Typer des instances dans des systèmes d'injection de dépendances ou factories génériques.
Option tsconfig qui garantit que chaque fichier peut être transpilé isolément, sans analyse inter-fichiers (compatible Babel, esbuild, SWC, Oxc). Elle interdit par exemple le ré-export d'un type sans le mot-clé type. Son complément récent est --erasableSyntaxOnly (TS 5.8, 28 février 2025), qui bannit la syntaxe non effaçable (enum, namespace avec code, propriétés de paramètre) pour le type stripping natif de Node.js.
Comme une règle qui dit que chaque chapitre d'un livre doit être compréhensible seul, sans lire les autres.
// tsconfig.json
{ "compilerOptions": { "isolatedModules": true } }
// Interdit: export { Type } from "./types"
// OK: export type { Type } from "./types"Cas d'usage : Obligatoire dès qu'un transpileur non-TS produit le JavaScript : Vite 8 (Oxc), esbuild, SWC, ou Node.js exécutant directement un fichier .ts.
Possibilité dans un mapped type de renommer les clés via la clause as. Permet de filtrer, transformer ou préfixer les clés d'un type.
Comme un rebranding — même produit, mais chaque nom est transforme selon une nouvelle convention.
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
type UserGetters = Getters<{ name: string }>;
// { getName: () => string }Cas d'usage : Générer automatiquement des noms de getters/setters ou filtrer des clés par type.
Types qui représentent une valeur exacte plutôt qu'une catégorie. Permet de restreindre une variable a des valeurs précises comme "GET" | "POST".
Comme un menu fixe au restaurant — vous ne pouvez choisir que parmi les plats proposes, pas inventer le votre.
type Method = "GET" | "POST" | "PUT";
const req = (method: Method) => fetch("/", { method });
req("GET"); // OK
// req("PATCH"); // ErreurCas d'usage : Restreindre les paramètrès de configuration aux seules valeurs valides.
Types qui transforment chaque propriété d'un type existant via une itération sur ses clés. Base de Partial, Required, Readonly et autres utility types.
Comme une chaîne de montage qui applique la même transformation a chaque pièce — chaque propriété passe par le même moule.
type Optional<T> = {
[K in keyof T]?: T[K];
};
interface User { name: string; age: number }
type PartialUser = Optional<User>;
// { name?: string; age?: number }Cas d'usage : Créer des variantes de types existants (formulaires partiels, versions readonly, DTOs).
Technique pour ajouter des déclarations a un module existant via déclaré module. Permet d'étendre les types d'une lib tierce.
Comme ajouter une extension a une maison existante — la structure originale reste intacte mais gagne de nouvelles pièces.
// Etendre express
declare module "express" {
interface Request {
userId?: string;
}
}Cas d'usage : Ajouter des propriétés typées aux objets de frameworks (Request express, Session, Window).
Type utilitaire intrinsèque ajouté en TypeScript 5.4 (6 mars 2024). Envelopper un paramètre dans NoInfer<T> l'exclut des candidats à l'inférence de T : le type générique est alors déduit uniquement des autres arguments, et l'argument marqué est simplement vérifié contre lui.
Dans un jury, le témoin qui n'a pas le droit de vote mais doit quand même respecter le verdict.
function feu<C extends string>(couleurs: C[], defaut?: NoInfer<C>) {}
feu(['rouge', 'vert'], 'rouge'); // OK
feu(['rouge', 'vert'], 'bleu');
// ❌ 'bleu' n'est pas assignable à 'rouge' | 'vert'
// Sans NoInfer, C serait inféré 'rouge' | 'vert' | 'bleu' : pas d'erreurCas d'usage : Fonctions où un argument « valeur par défaut » ou « clé » doit appartenir à un ensemble déduit d'un autre argument.
Utility type qui retire null et undefined d'une union. Garantit qu'une valeur existe réellement.
Comme un contrôle qualité qui rejette les boites vides — seuls les produits réels passent.
type Maybe = string | null | undefined;
type Sure = NonNullable<Maybe>; // stringCas d'usage : Nettoyer les types après une vérification de nullité pour travailler avec des valeurs garanties.
Utility type qui crée un nouveau type en excluant certaines propriétés. Inverse de Pick — on retire au lieu de sélectionner.
Comme un menu sans allergenes — on retire les ingrédients problématiques et on garde le reste.
interface User { id: string; name: string; password: string }
type SafeUser = Omit<User, "password">;
// { id: string; name: string }Cas d'usage : Exclure des champs sensibles (password, token) des types de réponse API.
Utility type qui retire le paramètre this d'une signature de fonction. Produit une fonction callable sans contexte spécifique.
Comme détacher un badge nominatif d'un uniforme — la fonction devient anonyme et utilisable par tous.
function greet(this: { name: string }) {
return this.name;
}
type Plain = OmitThisParameter<typeof greet>;
// () => string
const fn: Plain = greet.bind({ name: "A" });Cas d'usage : Exposer des méthodes liées (bound) qui n'ont plus besoin de contexte this explicite.
Types dont la structure interne est masquée aux consommateurs. Seul le module créateur peut construire et inspecter la valeur. Variante plus stricte des branded types.
Comme une boite noire scellée — on sait ce qu'elle représente mais seul le fabricant peut l'ouvrir.
declare const __opaque: unique symbol;
type Opaque<T, K> = T & { [__opaque]: K };
type Token = Opaque<string, "Token">;
const createToken = (s: string): Token => s as Token;Cas d'usage : Encapsuler des tokens, identifiants ou valeurs validées pour empêcher la manipulation directe.
Plusieurs signatures de fonction déclarées avant l'implémentation pour décrire différentes combinaisons d'arguments/retours. L'implémentation doit être compatible avec toutes.
Comme un restaurant avec différents menus selon le nombre de convives — même cuisine, mais offres distinctes.
function parse(input: string): number;
function parse(input: number): string;
function parse(input: string | number) {
return typeof input === "string"
? parseInt(input) : input.toString();
}Cas d'usage : APIs avec des relations précises entre types d'entrée et de sortie (createElement, addEventListener).
Utility type qui extrait les types des paramètrès d'une fonction sous forme de tuple. Permet de réutiliser la signature d'une fonction.
Comme photographier les ingrédients d'un chef pour reproduire sa recette exactement.
function greet(name: string, age: number) {}
type Args = Parameters<typeof greet>;
// [string, number]
const args: Args = ["Alice", 30];Cas d'usage : Wrapper des fonctions existantes ou créer des décorateurs qui préservent la signature.
Utility type qui rend toutes les propriétés d'un type optionnelles. Équivalent a ajouter ? a chaque propriété.
Comme un formulaire ou aucun champ n'est obligatoire — remplissez ce que vous voulez.
interface User { name: string; age: number }
function update(id: string, data: Partial<User>) {
// data.name et data.age sont optionnels
}
update("1", { name: "Alice" }); // OKCas d'usage : Fonctions de mise a jour partielle (PATCH) ou options de configuration avec des valeurs par défaut.
Types parametriques dont le paramètre générique n'est pas utilise dans la structure mais sert de marqueur compile-time. Ajoutent de l'information de type sans coût runtime.
Comme un tampon invisible sur un billet — l'oeil nu ne le voit pas mais le scanner le détecte.
type Validated = { __validated: true };
type Raw = { __raw: true };
type Email<T> = string & { __phantom: T };
function validate(e: Email<Raw>): Email<Validated> {
if (!e.includes("@")) throw Error("Invalid");
return e as Email<Validated>;
}Cas d'usage : Marquer les étapes de validation (raw -> sanitized -> validated) au niveau du système de types.
Utility type qui extrait un sous-ensemble de propriétés d'un type existant. Créé un nouveau type avec seulement les clés spécifiées.
Comme choisir des ingrédients dans un buffet — on ne prend que ce dont on a besoin.
interface User { id: string; name: string; email: string }
type UserPreview = Pick<User, "id" | "name">;
// { id: string; name: string }Cas d'usage : Créer des DTOs légers pour les listes ou les réponses API partielles.
Système permettant de décomposer un gros projet en sous-projets TS avec des dépendances explicites. Chaque sous-projet se compile indépendamment.
Comme un immeuble modulaire — chaque étage est construit séparément puis assemble.
// tsconfig.json
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/api" }
]
}
// Build: tsc --buildCas d'usage : Monorepos et gros projets ou la compilation complète est trop lente — chaque module compile isolement.
Utility type qui rend toutes les propriétés en lecture seule. Toute tentative de mutation génère une erreur a la compilation.
Comme un document sous verre dans un musée — on peut le regarder mais pas le toucher.
interface State { count: number; name: string }
const state: Readonly<State> = { count: 0, name: "A" };
// state.count = 1; // Erreur: readonlyCas d'usage : Protéger l'état dans Redux/stores immutables ou les paramètrès de fonctions pures.
Utility type qui construit un type objet dont les clés sont de type K et les valeurs de type V. Alternative typée aux objets indexe.
Comme un tableau Excel avec des colonnes prédéfinies — chaque ligne a exactement les mêmes champs.
type Role = "admin" | "user" | "guest";
const permissions: Record<Role, string[]> = {
admin: ["read", "write", "delete"],
user: ["read", "write"],
guest: ["read"]
};Cas d'usage : Créer des dictionnaires/maps types pour des lookups, configurations par clé ou traductions.
Types conditionnels qui se referencent eux-mêmes pour traiter des structures de profondeur variable. Permettent des transformations profondes sur les types.
Comme une équipe de nettoyage qui descend étage par étage dans un immeuble — chaque niveau est traite avant de passer au suivant.
type DeepReadonly<T> = T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T;
type Nested = { a: { b: { c: string } } };
type R = DeepReadonly<Nested>;Cas d'usage : Créer des transformations profondes (DeepPartial, DeepReadonly, flatten) sur des structures imbriquées.
Types qui se referencent eux-mêmes, permettant de modéliser des structures arborescentes ou imbriquées comme du JSON, un DOM ou un système de fichiers.
Comme des poupées russes — chaque poupée contient potentiellement une autre poupée identique.
type Json =
| string
| number
| boolean
| null
| Json[]
| { [key: string]: Json };Cas d'usage : Modéliser des structures de données naturellement recursives (arbres, JSON, menus imbriques).
Utility type qui rend toutes les propriétés obligatoires. Inverse de Partial — supprime tous les modificateurs optionnels (?).
Comme un formulaire administratif ou chaque champ est marque d'un astérisque rouge — tout est obligatoire.
interface Config {
host?: string;
port?: number;
}
type FullConfig = Required<Config>;
// { host: string; port: number }Cas d'usage : Garantir qu'un objet de configuration est complet après la fusion avec les valeurs par défaut.
Utility type qui extrait le type de retour d'une fonction. Utile pour inférer des types sans les redeclarer.
Comme lire l'étiquette de sortie d'une machine sans devoir regarder ses rouages internes.
function createUser() {
return { id: "1", name: "Alice", active: true };
}
type User = ReturnType<typeof createUser>;
// { id: string; name: string; active: boolean }Cas d'usage : Inférer le type de retour de fonctions factory ou de hooks React sans duplication.
Opérateur introduit en TypeScript 4.9 qui vérifie qu'une valeur est conforme à un type sans élargir le type inféré. On garde la validation (clés manquantes, fautes de frappe) et la précision des littéraux pour l'autocomplétion.
Comme un contrôle qualité qui valide la conformité sans changer l'étiquette du produit.
type Colors = Record<string, [number, number, number]>;
const palette = {
red: [255, 0, 0],
green: [0, 255, 0],
} satisfies Colors;
palette.red; // type [number, number, number], pas ColorsCas d'usage : Valider une configuration tout en gardant l'autocompletion sur les clés et valeurs exactes.
Ensemble d'options (strictNullChecks, noImplicitAny, strictFunctionTypes, strictBindCallApply, etc.) activées d'un coup par strict. Depuis TypeScript 6.0 (23 mars 2026), strict vaut true par défaut : un projet sans tsconfig ou sans l'option est strict, et il faut écrire strict: false pour revenir en arrière.
Comme passer le contrôle technique en mode strict — plus de vérifications mais véhicule plus fiable.
// tsconfig.json
{
"compilerOptions": {
"strict": true
// Active: strictNullChecks, noImplicitAny,
// strictBindCallApply, strictFunctionTypes...
}
}Cas d'usage : Toujours activer strict en début de projet pour maximiser la sécurité du typage des le départ.
Système de typage ou la compatibilité est basée sur la structure (propriétés/méthodes) et non sur le nom du type. Deux types avec la même forme sont compatibles.
Comme un recruteur qui juge sur les compétences réelles plutôt que sur le diplôme — si tu sais faire le job, tu es accepte.
interface Point { x: number; y: number }
const p = { x: 1, y: 2, z: 3 };
const accept = (pt: Point) => pt.x;
accept(p); // OK: p a x et yCas d'usage : Permet l'interopérabilité entre modules sans couplage fort sur les noms de types.
Technique de parsing de chaînés au niveau des types via template literals et infer. Permet d'extraire des parties de routes, selectors CSS ou patterns.
Comme un scanner qui lit un code-barres et en extrait chaque segment d'information automatiquement.
type ParseRoute<T> = T extends `/${infer Seg}/${infer Rest}`
? Seg | ParseRoute<`/${Rest}`>
: T extends `/${infer Last}` ? Last : never;
type R = ParseRoute<"/users/123/posts">;
// "users" | "123" | "posts"Cas d'usage : Extraire des paramètrès de route, parser des DSL ou valider des formats de chaînés a la compilation.
Types construits via des template strings qui combinent des types littéraux. Permettent de générer dynamiquement des types a partir de patterns de chaînés.
Comme un générateur de noms compose — prénom + nom donne toutes les combinaisons possibles automatiquement.
type Event = "click" | "focus";
type Handler = `on${Capitalize<Event>}`;
// "onClick" | "onFocus"
type Locale = `${"en" | "fr"}-${"US" | "FR"}`;
// "en-US" | "en-FR" | "fr-US" | "fr-FR"Cas d'usage : Typer des clés CSS, des routes API ou des noms d'evenements générés dynamiquement.
Utility type qui extrait le type du paramètre this d'une fonction. Retourne unknown si pas de paramètre this explicite.
Comme identifier le propriétaire d'un outil en regardant l'étiquette sur la poignée.
function greet(this: { name: string }) {
return `Hello ${this.name}`;
}
type Ctx = ThisParameterType<typeof greet>;
// { name: string }Cas d'usage : Extraire le contexte this pour le réutiliser dans des décorateurs ou des wrappers de méthodes.
Instructions spéciales en commentaire (/// <référence ...>) en haut des fichiers pour inclure des types ou des fichiers de déclaration. Usage rare avec les modules modernes.
Comme une note en marge d'un manuscrit qui dit 'voir aussi le chapitre X' — une référence croisée.
/// <reference types="node" />
/// <reference path="./legacy.d.ts" />
// Charge les types node et le fichier legacyCas d'usage : Inclure des types globaux (DOM, Node) ou référencer des fichiers .d.ts dans des projets sans bundler.
@ts-expect-error supprime l'erreur suivante mais échoue si aucune erreur n'existe. @ts-ignore supprime silencieusement toute erreur. Préférer expect-error.
ts-expect-error: un parapluie qu'on range s'il ne pleut pas. ts-ignore: un mur anti-bruit permanent, même en silence.
// @ts-expect-error: test avec mauvais type intentionnel
const result = fn("wrong");
// @ts-ignore: supprime toute erreur (dangereux)
const risky = badCode();Cas d'usage : Tests ou le but est de vérifier le comportement avec des types invalides — expect-error est préférable.
Fichier de configuration central d'un projet TypeScript : options du compilateur, fichiers inclus, résolution des modules. Depuis TypeScript 6.0 (23 mars 2026), les valeurs par défaut ont changé : strict à true, module à esnext, target à es2025, types à [] et rootDir au dossier du tsconfig. TypeScript 7.0 (8 juillet 2026) supprime target es5, baseUrl, moduleResolution classic/node10 et les modules amd/umd/systemjs.
Comme le tableau de bord d'une voiture — tous les réglages du moteur TypeScript en un seul endroit.
{
"compilerOptions": {
"target": "es2025",
"module": "nodenext",
"strict": true,
"types": ["node"],
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"outDir": "dist"
},
"include": ["src"]
}Cas d'usage : Tout projet TypeScript commence par un tsconfig. Depuis 5.9, tsc --init génère un fichier minimal et prescriptif plutôt qu'un gabarit exhaustif commenté.
Standard de documentation pour TypeScript base sur JSDoc avec des tags normalises (@param, @returns, @example). Supporte par les IDEs et générateurs de docs.
Comme les notices d'utilisation standardisées — même format partout pour une compréhension universelle.
/**
* Calcule la TVA d'un montant.
* @param amount - Le montant HT
* @param rate - Le taux (defaut 0.2)
* @returns Le montant TTC
*/
function withTax(amount: number, rate = 0.2) {}Cas d'usage : Documenter les APIs publiques pour que les IDEs affichent l'aide contextuelle et générer la doc.
Expression qui affine le type dans une branche conditionnelle. Inclut typeof, instanceof, in et les prédicats de type personnalises (is).
Comme un vigile a l'entrée qui vérifie votre badge — une fois passe, on sait exactement qui vous êtes.
function isString(val: unknown): val is string {
return typeof val === "string";
}
if (isString(input)) {
input.toUpperCase(); // type string garanti
}Cas d'usage : Créer des gardes personnalises pour valider des données externes (API, formulaires) avec typage garanti.
Capacité de TypeScript a déduire automatiquement le type d'une variable a partir de sa valeur. Évite de déclarer explicitement chaque type.
Comme un serveur qui devine que vous voulez de l'eau en voyant votre verre vide, sans que vous le demandiez.
const name = "Alice"; // string infere
const nums = [1, 2, 3]; // number[] infere
const double = (x: number) => x * 2; // retour number infereCas d'usage : Laisser TS inférer les types évidents pour garder le code concis sans perdre la sécurité.
Processus de réduction d'un type large vers un type plus spécifique via des conditions. TS analyse le flux de contrôle pour affiner les types.
Comme un entonnoir qui filtre progressivement — on part d'un grand ensemble pour arriver a un élément précis.
function show(val: string | number) {
if (typeof val === "string") {
console.log(val.toUpperCase()); // string
} else {
console.log(val.toFixed(2)); // number
}
}Cas d'usage : Manipuler des union types en toute sécurité dans les branches conditionnelles.
Annotation de retour de fonction (param is Type) qui indique au compilateur qu'un narrowing a lieu. Permet de créer des type guards personnalises.
Comme un certificat d'authenticité — la fonction garantit l'identité du type en sortie.
interface Fish { swim(): void }
interface Bird { fly(): void }
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}Cas d'usage : Valider des données complexes (API responses, events) avec un typage garanti après la vérification.
Mécanisme ou TS élargit automatiquement un type littéral vers un type plus général. Une variable let initialisée a "hello" devient string, pas "hello".
Comme un cadre photo extensible qui s'adapte a toutes les tailles au lieu de rester fixe sur une seule dimension.
let x = "hello"; // type: string (widened)
const y = "hello"; // type: "hello" (literal)
let z: "hello" = "hello"; // type: "hello" (explicite)Cas d'usage : Comprendre le widening pour éviter les erreurs avec les types littéraux dans les fonctions.
Technique avancée consistant a écrire de la logique (conditions, boucles, pattern matching) entièrement dans le système de types TS, sans code runtime.
Comme résoudre des équations sur un tableau blanc — tout se passe dans la théorie, rien n'est exécuté.
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>; // false
type Length<T extends any[]> =
T extends { length: infer L } ? L : never;Cas d'usage : Créer des validations de types complexes dans les bibliothèques (zod, tRPC, Prisma).
Pattern d'event emitter ou les noms d'evenements et leurs payloads sont types statiquement. Garantit la correspondance émit/on a la compilation.
Comme un standard téléphonique type — chaque extension a un format de message prédéfini, pas de mauvaise connexion.
type Events = { login: { userId: string }; logout: void };
class Emitter<T extends Record<string, any>> {
on<K extends keyof T>(event: K, fn: (data: T[K]) => void) {}
emit<K extends keyof T>(event: K, data: T[K]) {}
}
const bus = new Emitter<Events>();Cas d'usage : Systèmes event-driven (WebSocket, pub/sub, bus d'evenements) avec garantie de type sur les payloads.
TypeScript 6.0 (23 mars 2026) est la dernière version écrite en JavaScript et fait le pont vers la 7.0 native. Elle change les défauts (strict: true, module: esnext, target: es2025, types: [], rootDir au dossier du tsconfig), supprime outFile, target es5, moduleResolution classic et les modules amd/umd/systemjs, et déprécie baseUrl, node10 et les import assertions (assert → with). Ses types ajoutent Temporal, RegExp.escape et les méthodes getOrInsert.
La dernière station avant le changement de ligne : on y met ses bagages en ordre.
{
"compilerOptions": {
"ignoreDeprecations": "6.0",
"types": ["node"],
"paths": { "#/*": ["./src/*"] },
"strict": true
}
}Cas d'usage : Préparer une base de code à TypeScript 7 : corriger les dépréciations en 6.0, où elles sont encore des avertissements contournables.
TypeScript 7.0 (8 juillet 2026) est la réécriture du compilateur en Go, nom de code « Project Corsa », publiée d'abord en aperçu sous @typescript/native-preview (binaire tsgo). Le paquet typescript 7.x fournit un tsc natif multithread annoncé 8 à 12 fois plus rapide sur un build complet (VS Code : 125,7 s → 10,6 s) avec 6 à 26 % de mémoire en moins, et un serveur de langage LSP. Il reste compatible avec le comportement de vérification de TS 6.0 ; @typescript/typescript6 permet de garder l'ancienne API JavaScript côte à côte.
Le même chef, la même recette, mais une cuisine professionnelle avec dix fourneaux au lieu d'une plaque.
# Aperçu natif (avant 7.0)
npm i -D @typescript/native-preview
npx tsgo --project tsconfig.json
# TypeScript 7 : tsc est natif
npm i -D typescript@7
npx tsc -p .
# Outils qui ont besoin de l'ancienne API JS
npm i -D @typescript/typescript6@npm:typescript@6Cas d'usage : Monorepos et CI lentes ; éditeurs sur grosses bases ; linters typés (Oxlint s'appuie sur tsgo).
Quatre types spéciaux: any désactivé le typage, unknown force la vérification avant usage, never représente l'impossible, void l'absence de retour.
any: joker sans règles. unknown: colis suspect a inspecter. never: porte murée. void: accusé de réception sans contenu.
function fail(): never { throw new Error(); }
function log(): void { console.log("ok"); }
function parse(x: unknown) {
if (typeof x === "string") x.trim(); // OK
}Cas d'usage : Utiliser unknown pour les données externes (API), void pour les callbacks, never pour l'exhaustivité.
Utility types integres qui transforment les types littéraux de chaînés. Uppercase met en majuscules, Lowercase en minuscules, Capitalize la première lettre.
Comme les boutons de mise en forme dans un traitement de texte, mais appliques directement aux types.
type A = Uppercase<"hello">; // "HELLO"
type B = Lowercase<"HELLO">; // "hello"
type C = Capitalize<"hello">; // "Hello"
type D = Uncapitalize<"Hello">; // "hello"Cas d'usage : Transformer des clés de types dans des mapped types ou template literals (getters, event handlers).
Extension des tuples permettant d'utiliser des spreads génériques (...T) dans les types tuple. Permet de composer et manipuler des tuples de longueur variable.
Comme des wagons de train modulaires — on peut insérer, retirer ou combiner des sections librement.
type Concat<A extends any[], B extends any[]> = [...A, ...B];
type R = Concat<[1, 2], [3, 4]>; // [1, 2, 3, 4]
function head<T, U extends any[]>(arr: [T, ...U]): T {
return arr[0];
}Cas d'usage : Typer des fonctions avec des arguments variadiques (pipe, compose, curry) de manière précise.
Annotations explicites sur les paramètrès génériques pour déclarer la covariance (out), la contravariance (in) ou l'invariance. Ajoutées en TS 4.7.
Comme des panneaux 'entrée' et 'sortie' sur un parking — ils précisent dans quel sens circule le type.
interface Producer<out T> { get(): T }
interface Consumer<in T> { accept(val: T): void }
// Producer<Dog> assignable a Producer<Animal>
// Consumer<Animal> assignable a Consumer<Dog>Cas d'usage : Documenter et vérifier la variance des types génériques dans les APIs de bibliothèques complexes.