TypeScript 67 termes

67 termes affichés

TypeBestPractice Concept DataStructure Pattern Tool
Niveau 🟢 Junior 🟡 Mid 🔴 Senior

Ambient Declarations (.d.ts)

TypeScript 🟡 Mid

Fichiers de declaration (.d.ts) qui decrivent la forme de code JavaScript existant sans implementation. Permettent a TS de typer des libs JS.

Comme un plan architectural sans les murs reels — il decrit la structure sans la construire.

// globals.d.ts
declare const API_URL: string;
declare function legacy(x: number): string;
// Utilisable partout sans import

Cas d'usage : Typer des bibliotheques JavaScript, des variables globales injectees ou du code legacy.

Anti-pattern : Ecrire des .d.ts quand on peut simplement ecrire du .ts — les declarations ne sont utiles que pour du JS pur.
#core#tooling

Assertion Function

TypeScript 🔴 Senior

Fonction avec une signature asserts qui lance une erreur si la condition n'est pas remplie. Apres l'appel, le type est narrowe pour le reste du scope.

Comme un douanier qui refuse l'entree et arrete 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 ici

Cas d'usage : Validation stricte en debut de fonction qui narrowe les types pour tout le reste du bloc.

Anti-pattern : Oublier le throw dans l'assertion — la fonction ne lance pas et le narrowing est incorrect.
#advanced#safety

Awaited<T>

TypeScript 🟡 Mid

Utility type qui decompresse recursivement les Promise imbriquees pour obtenir le type de la valeur resolue finale.

Comme ouvrir des paquets cadeaux emboites 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>; // string

Cas d'usage : Obtenir le type resolu d'une fonction async ou d'une chaine de Promises pour le typage correct.

#core#utility-types

Branded / Nominal Types

TypeScript 🔴 Senior

Technique pour simuler du typage nominal en ajoutant une propriete fantome (brand) a un type. Empeche le melange accidentel de types structurellement identiques.

Comme des billets de differentes devises — meme papier, meme forme, mais on ne melange 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)); // Erreur

Cas d'usage : Distinguer des IDs, devises ou unites de mesure qui sont structurellement des strings/numbers.

Anti-pattern : Utiliser des types simples (string, number) pour des IDs de domaines differents — un userId passe en orderId compile sans erreur.
#advanced#pattern#safety

Builder Pattern Type

TypeScript 🔴 Senior

Implementation du Builder pattern avec un typage qui evolue a chaque etape. Chaque methode retourne un type plus precis, garantissant la completude a la compilation.

Comme un formulaire multi-etapes 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.

Anti-pattern : Builder sans typage progressif — rien n'empeche d'appeler build() avant d'avoir configure les champs requis.
#advanced#pattern

Conditional Types (infer)

TypeScript 🔴 Senior

Types qui selectionnent un type selon une condition (T extends U ? X : Y). Le mot-cle 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>;          // number

Cas d'usage : Extraire des types imbriques (retour de Promise, elements de tableau, props de composants React).

Anti-pattern : Imbriquer trop de conditional types — le code devient illisible et les erreurs cryptiques.
#advanced#interview#type-system

const assertion (as const)

TypeScript 🟡 Mid

Assertion qui empeche le widening et rend toutes les proprietes readonly et les valeurs litterales. Transforme un objet/tableau en version profondement immutable.

Comme graver dans le marbre — une fois ecrit, chaque detail 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 : Creer des constantes avec des types litteraux exacts pour les discriminated unions et les lookups.

Anti-pattern : Oublier as const sur des tableaux utilises comme union — ["a", "b"] donne string[] au lieu de readonly ["a", "b"].
#core#interview#best-practice

ConstructorParameters<T>

TypeScript 🟡 Mid

Utility type qui extrait les types des parametres du constructeur d'une classe sous forme de tuple.

Comme lire la notice de montage d'un meuble pour savoir quels outils sont necessaires.

class Service {
  constructor(public url: string, public timeout: number) {}
}
type Args = ConstructorParameters<typeof Service>;
// [string, number]

Cas d'usage : Creer des factory functions ou des conteneurs d'injection de dependances types.

#utility-types#advanced

Covariance / Contravariance

TypeScript 🔴 Senior

Covariance: un sous-type peut remplacer le type parent (sortie). Contravariance: le type parent peut remplacer le sous-type (entree). Determine la compatibilite des generics.

Covariance: un chien peut passer la ou un animal est attendu (du specifique au general). 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 OK

Cas d'usage : Comprendre pourquoi certaines assignations generiques echouent et concevoir des APIs correctement typees.

#advanced#interview#type-system

Declaration Maps

TypeScript 🔴 Senior

Fichiers .d.ts.map qui lient les declarations aux sources originales. Permettent 'Go to Definition' de naviguer vers le .ts source au lieu du .d.ts.

Comme un GPS qui mene directement a l'usine au lieu de s'arreter a la vitrine du magasin.

// tsconfig.json
{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  }
}

Cas d'usage : Monorepos et bibliotheques ou les developpeurs doivent naviguer vers le code source des dependances.

#tooling#monorepo

Declaration Merging

TypeScript 🔴 Senior

Mecanisme ou plusieurs declarations du meme nom sont fusionnees en une seule definition. S'applique aux interfaces, namespaces et enums.

Comme deux equipes qui construisent chacune une aile du meme batiment — a la fin, c'est un seul edifice.

interface Box { width: number }
interface Box { height: number }
// Box = { width: number; height: number }
const b: Box = { width: 10, height: 20 };

Cas d'usage : Etendre les types de bibliotheques tierces sans modifier leur code source.

Anti-pattern : Abuser du merging pour patcher des types au lieu de creer des extensions propres — difficulte de traçabilité.
#advanced#interview

Decorator (legacy + stage 3)

TypeScript 🔴 Senior

Syntaxe @decorator pour modifier ou annoter des classes et leurs membres. TS supporte les decorateurs legacy (experimentalDecorators) et le standard TC39 stage 3 (TS 5.0+).

Comme un cadre autour d'un tableau — il enveloppe l'oeuvre sans la modifier, en ajoutant du contexte.

// Stage 3 decorator (TS 5.0+)
function log(_target: any, ctx: ClassMethodDecoratorContext) {
  console.log(`Decorating ${String(ctx.name)}`);
}
class Api {
  @log greet() { return "hi"; }
}

Cas d'usage : AOP (logging, auth, validation) dans les frameworks comme Angular, NestJS ou TypeORM.

Anti-pattern : Mixer les decorateurs legacy et stage 3 dans le meme projet — incompatibilite et confusion.
#advanced#pattern#framework

Default Generic

TypeScript 🟡 Mid

Valeur par defaut assignee a un parametre generique, utilisee quand le type n'est pas explicitement fourni ni inferable. Similaire aux parametres par defaut de fonctions.

Comme la taille standard d'un vetement — si vous ne precisez 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 defaut dans les bibliotheques pour simplifier l'usage basique tout en permettant la personalisation.

#generics#api-design

Discriminated Union

TypeScript 🟡 Mid

Union de types partageant une propriete commune (discriminant) qui permet a TS de distinguer chaque variante. Pattern fondamental pour modeliser des etats.

Comme des colis avec une etiquette 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 : Modeliser des etats applicatifs (loading/success/error) avec exhaustivite garantie par le compilateur.

Anti-pattern : Utiliser des booleens multiples (isLoading, hasError) au lieu d'une union discriminee — etats impossibles deviennent possibles.
#core#interview#pattern

Distributive Conditional Types

TypeScript 🔴 Senior

Quand un type conditionnel agit sur un parametre generique nu (T extends U), il se distribue sur chaque membre d'une union. Chaque membre est evalue independamment.

Comme un tri postal — chaque lettre de la pile est examinees individuellement et envoyee 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 independamment (Exclude, Extract fonctionnent ainsi).

Anti-pattern : Ne pas comprendre la distribution et obtenir des resultats inattendus — utiliser [T] extends [U] pour la desactiver.
#advanced#type-system

Enum vs const Enum vs Union

TypeScript 🟡 Mid

Trois facons de modeliser un ensemble fini: enum (objet runtime), const enum (inline a la compilation, efface), union de litteraux (zero runtime). Chacune avec ses compromis.

Enum: un panneau permanent. Const enum: un post-it qu'on retire apres lecture. Union: une regle 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 runtime

Cas d'usage : Preferer les unions de litteraux pour la legerete. Enum pour l'iteration. Const enum pour la performance (avec precaution).

Anti-pattern : Utiliser des enums numeriques sans valeur explicite — l'ajout d'un membre casse les valeurs persistees.
#core#interview#best-practice

Exclude<T, U>

TypeScript 🟡 Mid

Utility type qui retire d'une union T tous les membres assignables a U. Fonctionne sur les unions de types, pas sur les proprietes d'objets.

Comme un filtre a cafe 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 creer des sous-ensembles de types (evenements, statuts, permissions).

#core#interview#utility-types

Exhaustive Check (never)

TypeScript 🟡 Mid

Technique utilisant le type never pour garantir que tous les cas d'une union sont traites. Si un cas est oublie, le compilateur genere une erreur.

Comme une checklist de securite en aviation — chaque point doit etre coche, aucun oubli n'est tolere.

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 gere partout dans le code.

Anti-pattern : Mettre un default generique qui ignore les nouveaux cas — les bugs passent en silence.
#core#interview#safety

Extract<T, U>

TypeScript 🟡 Mid

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 metal.

type Mixed = string | number | boolean | null;
type Primitives = Extract<Mixed, string | number>;
// string | number

Cas d'usage : Extraire les types specifiques d'une large union pour un traitement specialise.

#core#utility-types

Generic Constraint (extends)

TypeScript 🟡 Mid

Restriction appliquee a un parametre generique via extends pour garantir qu'il possede certaines proprietes. 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 length

Cas d'usage : Garantir qu'un generique possede les proprietes necessaires avant de les utiliser.

Anti-pattern : Contraindre trop largement (extends object) ou pas assez — soit trop restrictif, soit pas assez sur.
#core#interview#generics

Generic Function

TypeScript 🟡 Mid

Fonction parametree par un ou plusieurs types qui sont resolus a l'appel. Permet d'ecrire du code reutilisable tout en conservant la securite des types.

Comme un moule a gateau adaptable — meme forme de base mais le resultat s'adapte a l'ingredient (chocolat, vanille).

function first<T>(arr: T[]): T | undefined {
  return arr[0];
}
const n = first([1, 2, 3]); // number
const s = first(["a", "b"]); // string

Cas d'usage : Creer des fonctions utilitaires (map, filter, fetch wrapper) qui preservent les types d'entree/sortie.

Anti-pattern : Utiliser any au lieu de generics — on perd completement la securite de type en sortie.
#core#interview#generics

Generic Inference

TypeScript 🟡 Mid

Capacite de TS a deduire automatiquement les parametres generiques a partir des arguments passes. Evite de specifier explicitement les types a chaque appel.

Comme un traducteur qui detecte 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 string

Cas d'usage : Concevoir des APIs generiques ergonomiques ou l'utilisateur n'a pas a specifier les types manuellement.

#generics#core

Global Augmentation

TypeScript 🔴 Senior

Technique pour ajouter des declarations au scope global via declare global dans un module. Permet d'etendre Window, globalThis ou les prototypes.

Comme un decret national qui ajoute une loi applicable partout — la modification est globale.

export {};
declare global {
  interface Window {
    analytics: { track(e: string): void };
  }
}

Cas d'usage : Declarer des variables globales injectees (analytics, config, feature flags) avec un typage correct.

Anti-pattern : Polluer le scope global au lieu d'utiliser des imports — retour aux problemes pre-modules.
#advanced#tooling

Incremental Compilation

TypeScript 🟡 Mid

Option (incremental: true) qui sauvegarde un cache (.tsbuildinfo) pour ne recompiler que les fichiers modifies. Accelere drastiquement les rebuilds.

Comme un cuisinier qui ne recoupe que les legumes manquants au lieu de tout reprendre a zero.

// tsconfig.json
{
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": "./.tsbuildinfo"
  }
}

Cas d'usage : Tout projet de taille moyenne+ devrait activer l'incremental pour des temps de build reduits.

#tooling#performance

InstanceType<T>

TypeScript 🟡 Mid

Utility type qui extrait le type d'instance d'un constructeur de classe. Utile quand on travaille avec typeof Class.

Comme connaitre 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 systemes d'injection de dependances ou factories generiques.

#utility-types

isolatedModules

TypeScript 🟡 Mid

Flag tsconfig qui garantit que chaque fichier peut etre transpile isolement (compatible Babel, esbuild, SWC). Interdit les constructions qui necessitent une analyse multi-fichiers.

Comme une regle qui dit que chaque chapitre d'un livre doit etre comprehensible 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 quand on utilise des transpileurs non-TS (Babel, esbuild, Vite) pour garantir la compatibilite.

Anti-pattern : Desactiver isolatedModules avec esbuild/Vite — des re-exports de types cassent silencieusement le build.
#tooling#best-practice

Key Remapping (as)

TypeScript 🔴 Senior

Possibilite dans un mapped type de renommer les cles via la clause as. Permet de filtrer, transformer ou prefixer les cles d'un type.

Comme un rebranding — meme 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 : Generer automatiquement des noms de getters/setters ou filtrer des cles par type.

#advanced#type-system

Literal Types

TypeScript 🟢 Junior

Types qui representent une valeur exacte plutot qu'une categorie. Permet de restreindre une variable a des valeurs precises 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"); // Erreur

Cas d'usage : Restreindre les parametres de configuration aux seules valeurs valides.

Anti-pattern : Utiliser string la ou un ensemble fini de valeurs est attendu — aucune aide de l'autocompletion.
#core#interview#beginner

Mapped Types

TypeScript 🟡 Mid

Types qui transforment chaque propriete d'un type existant via une iteration sur ses cles. Base de Partial, Required, Readonly et autres utility types.

Comme une chaine de montage qui applique la meme transformation a chaque piece — chaque propriete passe par le meme 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 : Creer des variantes de types existants (formulaires partiels, versions readonly, DTOs).

Anti-pattern : Redefinir manuellement chaque variante d'un type au lieu d'utiliser un mapped type — duplication et desynchronisation.
#core#interview#type-system

Module Augmentation

TypeScript 🔴 Senior

Technique pour ajouter des declarations a un module existant via declare module. Permet d'etendre les types d'une lib tierce.

Comme ajouter une extension a une maison existante — la structure originale reste intacte mais gagne de nouvelles pieces.

// Etendre express
declare module "express" {
  interface Request {
    userId?: string;
  }
}

Cas d'usage : Ajouter des proprietes typees aux objets de frameworks (Request express, Session, Window).

Anti-pattern : Augmenter des modules sans documenter pourquoi — les futurs developpeurs ne comprennent pas d'ou viennent les types.
#advanced#tooling

NonNullable<T>

TypeScript 🟢 Junior

Utility type qui retire null et undefined d'une union. Garantit qu'une valeur existe reellement.

Comme un controle qualite qui rejette les boites vides — seuls les produits reels passent.

type Maybe = string | null | undefined;
type Sure = NonNullable<Maybe>; // string

Cas d'usage : Nettoyer les types apres une verification de nullite pour travailler avec des valeurs garanties.

#core#utility-types

Omit<T, K>

TypeScript 🟢 Junior

Utility type qui cree un nouveau type en excluant certaines proprietes. Inverse de Pick — on retire au lieu de selectionner.

Comme un menu sans allergenes — on retire les ingredients problematiques 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 reponse API.

#core#interview#utility-types

OmitThisParameter<T>

TypeScript 🔴 Senior

Utility type qui retire le parametre this d'une signature de fonction. Produit une fonction callable sans contexte specifique.

Comme detacher 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 methodes liees (bound) qui n'ont plus besoin de contexte this explicite.

#advanced#utility-types

Opaque Types

TypeScript 🔴 Senior

Types dont la structure interne est masquee aux consommateurs. Seul le module createur peut construire et inspecter la valeur. Variante plus stricte des branded types.

Comme une boite noire scellée — on sait ce qu'elle represente 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 validees pour empecher la manipulation directe.

#advanced#pattern#safety

Overload Signatures

TypeScript 🟡 Mid

Plusieurs signatures de fonction declarees avant l'implementation pour decrire differentes combinaisons d'arguments/retours. L'implementation doit etre compatible avec toutes.

Comme un restaurant avec differents menus selon le nombre de convives — meme 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 precises entre types d'entree et de sortie (createElement, addEventListener).

Anti-pattern : Utiliser des overloads quand une simple union ou un generic suffirait — complexite inutile.
#core#interview#api-design

Parameters<T>

TypeScript 🟡 Mid

Utility type qui extrait les types des parametres d'une fonction sous forme de tuple. Permet de reutiliser la signature d'une fonction.

Comme photographier les ingredients 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 creer des decorateurs qui preservent la signature.

#core#utility-types

Partial<T>

TypeScript 🟢 Junior

Utility type qui rend toutes les proprietes d'un type optionnelles. Equivalent a ajouter ? a chaque propriete.

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" }); // OK

Cas d'usage : Fonctions de mise a jour partielle (PATCH) ou options de configuration avec des valeurs par defaut.

Anti-pattern : Utiliser Partial partout et perdre la garantie que les champs requis sont presents a la creation.
#core#interview#utility-types

Phantom Types

TypeScript 🔴 Senior

Types parametriques dont le parametre generique n'est pas utilise dans la structure mais sert de marqueur compile-time. Ajoutent de l'information de type sans cout runtime.

Comme un tampon invisible sur un billet — l'oeil nu ne le voit pas mais le scanner le detecte.

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 etapes de validation (raw -> sanitized -> validated) au niveau du systeme de types.

#advanced#pattern#safety

Pick<T, K>

TypeScript 🟢 Junior

Utility type qui extrait un sous-ensemble de proprietes d'un type existant. Cree un nouveau type avec seulement les cles specifiees.

Comme choisir des ingredients 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 : Creer des DTOs legers pour les listes ou les reponses API partielles.

#core#interview#utility-types

Project References

TypeScript 🔴 Senior

Systeme permettant de decomposer un gros projet en sous-projets TS avec des dependances explicites. Chaque sous-projet se compile independamment.

Comme un immeuble modulaire — chaque etage est construit separement puis assemble.

// tsconfig.json
{
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/api" }
  ]
}
// Build: tsc --build

Cas d'usage : Monorepos et gros projets ou la compilation complete est trop lente — chaque module compile isolement.

#tooling#performance#monorepo

Readonly<T>

TypeScript 🟢 Junior

Utility type qui rend toutes les proprietes en lecture seule. Toute tentative de mutation genere une erreur a la compilation.

Comme un document sous verre dans un musee — 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: readonly

Cas d'usage : Proteger l'etat dans Redux/stores immutables ou les parametres de fonctions pures.

Anti-pattern : Oublier que Readonly est superficiel — les objets imbriques restent mutables.
#core#interview#utility-types

Record<K, V>

TypeScript 🟢 Junior

Utility type qui construit un type objet dont les cles sont de type K et les valeurs de type V. Alternative typee aux objets indexe.

Comme un tableau Excel avec des colonnes predefinies — chaque ligne a exactement les memes champs.

type Role = "admin" | "user" | "guest";
const permissions: Record<Role, string[]> = {
  admin: ["read", "write", "delete"],
  user: ["read", "write"],
  guest: ["read"]
};

Cas d'usage : Creer des dictionnaires/maps types pour des lookups, configurations par cle ou traductions.

Anti-pattern : Utiliser { [key: string]: any } au lieu de Record avec des cles precises — perte d'autocompletion.
#core#interview#utility-types

Recursive Conditional Types

TypeScript 🔴 Senior

Types conditionnels qui se referencent eux-memes pour traiter des structures de profondeur variable. Permettent des transformations profondes sur les types.

Comme une equipe de nettoyage qui descend etage par etage 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 : Creer des transformations profondes (DeepPartial, DeepReadonly, flatten) sur des structures imbriquees.

Anti-pattern : Recursion trop profonde sans limite — TS a une profondeur max (~50) et genere des erreurs cryptiques.
#advanced#type-system

Recursive Types

TypeScript 🔴 Senior

Types qui se referencent eux-memes, permettant de modeliser des structures arborescentes ou imbriquees comme du JSON, un DOM ou un systeme de fichiers.

Comme des poupees russes — chaque poupee contient potentiellement une autre poupee identique.

type Json =
  | string
  | number
  | boolean
  | null
  | Json[]
  | { [key: string]: Json };

Cas d'usage : Modeliser des structures de donnees naturellement recursives (arbres, JSON, menus imbriques).

Anti-pattern : Creer des recursions infinies sans condition d'arret — le compilateur plante ou devient tres lent.
#advanced#type-system

Required<T>

TypeScript 🟢 Junior

Utility type qui rend toutes les proprietes obligatoires. Inverse de Partial — supprime tous les modificateurs optionnels (?).

Comme un formulaire administratif ou chaque champ est marque d'un asterisque 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 apres la fusion avec les valeurs par defaut.

#core#utility-types

ReturnType<T>

TypeScript 🟡 Mid

Utility type qui extrait le type de retour d'une fonction. Utile pour inferer des types sans les redeclarer.

Comme lire l'etiquette 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 : Inferer le type de retour de fonctions factory ou de hooks React sans duplication.

Anti-pattern : Declarer manuellement un type qui duplique le retour d'une fonction — desynchronisation garantie.
#core#interview#utility-types

satisfies operator

TypeScript 🟡 Mid

Operateur qui verifie qu'une valeur est conforme a un type sans elargir le type infere. Combine la validation de type avec la preservation du type litteral.

Comme un controle qualite qui valide la conformite sans changer l'etiquette 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 Colors

Cas d'usage : Valider une configuration tout en gardant l'autocompletion sur les cles et valeurs exactes.

Anti-pattern : Utiliser un type annotation qui elargit le type et perd l'autocompletion sur les cles specifiques.
#core#interview#ts5

Strict Mode Flags

TypeScript 🟡 Mid

Ensemble de flags dans tsconfig (strict: true) qui activent toutes les verifications strictes: strictNullChecks, noImplicitAny, strictFunctionTypes, etc.

Comme passer le controle technique en mode strict — plus de verifications mais vehicule plus fiable.

// tsconfig.json
{
  "compilerOptions": {
    "strict": true
    // Active: strictNullChecks, noImplicitAny,
    // strictBindCallApply, strictFunctionTypes...
  }
}

Cas d'usage : Toujours activer strict en debut de projet pour maximiser la securite du typage des le depart.

Anti-pattern : Desactiver strict pour faire compiler du code existant — repousse la dette technique en la multipliant.
#core#best-practice#tooling

Structural Typing

TypeScript 🟡 Mid

Systeme de typage ou la compatibilite est basee sur la structure (proprietes/methodes) et non sur le nom du type. Deux types avec la meme forme sont compatibles.

Comme un recruteur qui juge sur les competences reelles plutot que sur le diplome — 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 y

Cas d'usage : Permet l'interoperabilite entre modules sans couplage fort sur les noms de types.

Anti-pattern : Supposer que deux types avec le meme nom sont identiques — c'est la structure qui compte, pas le nom.
#core#interview#type-system

Template Literal Parsing

TypeScript 🔴 Senior

Technique de parsing de chaines 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 parametres de route, parser des DSL ou valider des formats de chaines a la compilation.

#advanced#pattern#type-system

Template Literal Types

TypeScript 🔴 Senior

Types construits via des template strings qui combinent des types litteraux. Permettent de generer dynamiquement des types a partir de patterns de chaines.

Comme un generateur de noms compose — prenom + 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 cles CSS, des routes API ou des noms d'evenements generes dynamiquement.

Anti-pattern : Generer des unions trop larges avec des template literals — explosion combinatoire qui ralentit le compilateur.
#advanced#interview#type-system

ThisParameterType<T>

TypeScript 🔴 Senior

Utility type qui extrait le type du parametre this d'une fonction. Retourne unknown si pas de parametre this explicite.

Comme identifier le proprietaire d'un outil en regardant l'etiquette sur la poignee.

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 reutiliser dans des decorateurs ou des wrappers de methodes.

#advanced#utility-types

Triple-Slash Directives

TypeScript 🔴 Senior

Instructions speciales en commentaire (/// <reference ...>) en haut des fichiers pour inclure des types ou des fichiers de declaration. Usage rare avec les modules modernes.

Comme une note en marge d'un manuscrit qui dit 'voir aussi le chapitre X' — une reference croisee.

/// <reference types="node" />
/// <reference path="./legacy.d.ts" />
// Charge les types node et le fichier legacy

Cas d'usage : Inclure des types globaux (DOM, Node) ou referencer des fichiers .d.ts dans des projets sans bundler.

Anti-pattern : Utiliser des triple-slash au lieu d'imports ES modules — methode obsolete dans les projets modernes.
#tooling#legacy

ts-expect-error vs ts-ignore

TypeScript 🟡 Mid

@ts-expect-error supprime l'erreur suivante mais echoue si aucune erreur n'existe. @ts-ignore supprime silencieusement toute erreur. Preferer expect-error.

ts-expect-error: un parapluie qu'on range s'il ne pleut pas. ts-ignore: un mur anti-bruit permanent, meme 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 verifier le comportement avec des types invalides — expect-error est preferable.

Anti-pattern : Utiliser ts-ignore pour faire compiler du code — masque les vrais bugs et empeche la detection de regressions.
#best-practice#tooling

tsconfig.json

TypeScript 🟢 Junior

Fichier de configuration central du projet TypeScript. Definit les options du compilateur, les fichiers a inclure/exclure et les chemins de resolution.

Comme le tableau de bord d'une voiture — tous les reglages du moteur TypeScript en un seul endroit.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "strict": true,
    "outDir": "dist"
  },
  "include": ["src"]
}

Cas d'usage : Tout projet TypeScript commence par un tsconfig qui definit les regles de compilation.

Anti-pattern : Copier un tsconfig generique sans comprendre les options — des conflits subtils emergent.
#core#tooling#beginner

TSDoc

TypeScript 🟢 Junior

Standard de documentation pour TypeScript base sur JSDoc avec des tags normalises (@param, @returns, @example). Supporte par les IDEs et generateurs de docs.

Comme les notices d'utilisation standardisees — meme format partout pour une comprehension 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 generer la doc.

Anti-pattern : Documenter chaque ligne triviale — le code devrait etre auto-explicatif, les docs pour les cas complexes.
#tooling#best-practice#beginner

Type Guard

TypeScript 🟡 Mid

Expression qui affine le type dans une branche conditionnelle. Inclut typeof, instanceof, in et les predicats de type personnalises (is).

Comme un vigile a l'entree qui verifie votre badge — une fois passe, on sait exactement qui vous etes.

function isString(val: unknown): val is string {
  return typeof val === "string";
}
if (isString(input)) {
  input.toUpperCase(); // type string garanti
}

Cas d'usage : Creer des gardes personnalises pour valider des donnees externes (API, formulaires) avec typage garanti.

Anti-pattern : Ecrire un type guard qui ne verifie pas reellement le type — le compilateur fait confiance au predicat.
#core#interview#safety

Type Inference

TypeScript 🟢 Junior

Capacite de TypeScript a deduire automatiquement le type d'une variable a partir de sa valeur. Evite de declarer 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 infere

Cas d'usage : Laisser TS inferer les types evidents pour garder le code concis sans perdre la securite.

Anti-pattern : Annoter explicitement chaque variable triviale (const x: number = 5) alourdit le code inutilement.
#core#interview#beginner

Type Narrowing

TypeScript 🟢 Junior

Processus de reduction d'un type large vers un type plus specifique via des conditions. TS analyse le flux de controle pour affiner les types.

Comme un entonnoir qui filtre progressivement — on part d'un grand ensemble pour arriver a un element precis.

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 securite dans les branches conditionnelles.

Anti-pattern : Utiliser des cast (as) au lieu de narrowing propre — on perd la verification du compilateur.
#core#interview#type-system

Type Predicate

TypeScript 🟡 Mid

Annotation de retour de fonction (param is Type) qui indique au compilateur qu'un narrowing a lieu. Permet de creer des type guards personnalises.

Comme un certificat d'authenticite — la fonction garantit l'identite 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 donnees complexes (API responses, events) avec un typage garanti apres la verification.

Anti-pattern : Ecrire un predicat incorrect (retourne true mais le type est faux) — le compilateur fait confiance aveugle.
#core#interview#safety

Type Widening

TypeScript 🟡 Mid

Mecanisme ou TS elargit automatiquement un type litteral vers un type plus general. Une variable let initialisee 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 eviter les erreurs avec les types litteraux dans les fonctions.

Anti-pattern : Utiliser let partout et perdre les types litteraux necessaires pour les discriminated unions.
#core#interview#type-system

Type-level Programming

TypeScript 🔴 Senior

Technique avancee consistant a ecrire de la logique (conditions, boucles, pattern matching) entierement dans le systeme de types TS, sans code runtime.

Comme resoudre des equations sur un tableau blanc — tout se passe dans la theorie, rien n'est execute.

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 : Creer des validations de types complexes dans les bibliotheques (zod, tRPC, Prisma).

Anti-pattern : Ecrire du type-level programming complexe pour des cas simples — maintenance cauchemardesque.
#advanced#type-system

Type-safe Event Emitter

TypeScript 🔴 Senior

Pattern d'event emitter ou les noms d'evenements et leurs payloads sont types statiquement. Garantit la correspondance emit/on a la compilation.

Comme un standard telephonique type — chaque extension a un format de message predefini, 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 : Systemes event-driven (WebSocket, pub/sub, bus d'evenements) avec garantie de type sur les payloads.

#advanced#pattern#real-world

unknown vs any vs never vs void

TypeScript 🟡 Mid

Quatre types speciaux: any desactive le typage, unknown force la verification avant usage, never represente l'impossible, void l'absence de retour.

any: joker sans regles. unknown: colis suspect a inspecter. never: porte muree. void: accusé de reception 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 donnees externes (API), void pour les callbacks, never pour l'exhaustivite.

Anti-pattern : Utiliser any pour 'faire compiler' — masque les bugs au lieu de les prevenir.
#core#interview#safety

Utility types integres qui transforment les types litteraux de chaines. Uppercase met en majuscules, Lowercase en minuscules, Capitalize la premiere 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 cles de types dans des mapped types ou template literals (getters, event handlers).

#utility-types#type-system

Variadic Tuple Types

TypeScript 🔴 Senior

Extension des tuples permettant d'utiliser des spreads generiques (...T) dans les types tuple. Permet de composer et manipuler des tuples de longueur variable.

Comme des wagons de train modulaires — on peut inserer, 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 maniere precise.

#advanced#type-system

Variance Annotations (in/out)

TypeScript 🔴 Senior

Annotations explicites sur les parametres generiques pour declarer la covariance (out), la contravariance (in) ou l'invariance. Ajoutees en TS 4.7.

Comme des panneaux 'entree' et 'sortie' sur un parking — ils precisent 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 verifier la variance des types generiques dans les APIs de bibliotheques complexes.

#advanced#type-system

Autres stacks

Advanced Ecosystem Architecture CSS-in-JS DevOps HTML / CSS JavaScript MongoDB Mongoose NestJS Personalities PHP PostgreSQL React Sass Styled-Components Tailwind CSS Testing WordPress
← Retour au lexique complet