1
Types primitifs & Annotations
TS
// Primitifs
let nom: string = "Alice";
let age: number = 30; // int et float = number
let big: bigint = 100n;
let ok: boolean = true;
let sym: symbol = Symbol("id");
let nul: null = null;
let und: undefined = undefined;
// SpΓ©ciaux
let anything: any = "no check"; // dΓ©sactive le type-checking β Γ©viter
let unknown_val: unknown = 42; // type-safe any β prΓ©fΓ©rer
function fail(): never { throw new Error(); } // jamais de retour
function log(): void { console.log("hi"); } // pas de valeur retour
// Arrays
let nums: number[] = [1, 2, 3];
let strs: Array<string> = ["a", "b"]; // forme gΓ©nΓ©rique
let matrix: number[][] = [[1,2],[3,4]];
// Tuples
let pair: [string, number] = ["Alice", 30];
let named: [name: string, age: number] = ["Bob", 25]; // labeled
let rest: [string, ...number[]] = ["sum", 1, 2, 3]; // variadic
const tuple = ["a", 1] as const; // readonly ["a", 1]
// Type inference β TS infΓ¨re quand c'est Γ©vident
const x = 42; // type: 42 (literal type)
let y = 42; // type: number (widening)2
Interfaces
TS
interface User {
readonly id: number; // lecture seule
name: string;
email?: string; // optionnel
age: number;
}
// Index signatures
interface Dict {
[key: string]: number; // clΓ©s string, valeurs number
}
// Callable / Constructable
interface Fn {
(x: number): string; // call signature
}
interface Ctor {
new (name: string): User; // construct signature
}
// HΓ©ritage (extends β multiple ok)
interface Admin extends User {
role: "admin" | "superadmin";
}
interface Timestamped {
createdAt: Date;
updatedAt: Date;
}
interface AdminTimestamped extends Admin, Timestamped {}
// Declaration merging (interface seulement, pas type)
interface User { phone?: string; } // s'ajoute Γ User existant
// Generic interface
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}3
Types & Alias
TS
// Type alias
type ID = string | number;
type Point = { x: number; y: number };
type Callback = (data: string) => void;
// Interface vs Type β quand utiliser quoi ?
// Interface : objets, classes (extends, implements, merging)
// Type : unions, intersections, tuples, mapped types, primitifs
// Object type
type Config = {
readonly host: string;
port?: number;
[key: string]: unknown;
};
// Record shorthand
type Scores = Record<string, number>; // { [key: string]: number }4
Union, Intersection, Literal Types
TS
// ββ Union : A OU B ββ
type Result = string | number | null;
type Status = "idle" | "loading" | "success" | "error";
// Discriminated union (pattern très courant)
type Shape =
| { kind: "circle"; radius: number }
| { kind: "rect"; width: number; height: number }
| { kind: "triangle"; base: number; height: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "rect": return s.width * s.height;
case "triangle": return s.base * s.height / 2;
default: const _exhaustive: never = s; return _exhaustive;
}
}
// ββ Intersection : A ET B ββ
type WithTimestamps = { createdAt: Date; updatedAt: Date };
type UserWithTimestamps = User & WithTimestamps;
// ββ Literal types ββ
type Direction = "up" | "down" | "left" | "right";
type Bit = 0 | 1;
type Bool = true | false;
// as const β assertion de constante
const COLORS = ["red", "green", "blue"] as const;
type Color = (typeof COLORS)[number]; // "red" | "green" | "blue"
// satisfies (TS 5.0) β valide le type sans le widener
const config = {
port: 3000,
host: "localhost",
} satisfies Record<string, string | number>;
// config.port est infΓ©rΓ© comme 3000 (literal), pas string | number5
Enums
TS
// Numeric enum (auto-incrΓ©mentΓ©)
enum Direction { Up, Down, Left, Right } // 0, 1, 2, 3
enum Status { Active = 1, Inactive = 2 }
// String enum (prΓ©fΓ©rer)
enum Role {
Admin = "ADMIN",
User = "USER",
Guest = "GUEST",
}
const r: Role = Role.Admin;
// const enum β inlinΓ© Γ la compilation (pas d'objet runtime)
const enum Color { Red, Green, Blue }
// Alternative moderne : union de littΓ©raux (souvent prΓ©fΓ©rΓ©)
type Role = "admin" | "user" | "guest";
// Reverse mapping (numeric enum seulement)
Direction[0] // "Up"
Direction.Up // 06
Fonctions typΓ©es
TS
// Paramètres et retour
function add(a: number, b: number): number { return a + b; }
// Arrow avec type
const add: (a: number, b: number) => number = (a, b) => a + b;
// Optionnels et dΓ©fauts
function greet(name: string, prefix?: string): string { ... }
function greet(name: string, prefix = "Hello"): string { ... }
// Rest params
function sum(...nums: number[]): number { ... }
// Function type alias
type Handler = (event: Event) => void;
type AsyncFn<T> = () => Promise<T>;
// Overloads
function parse(input: string): number;
function parse(input: number): string;
function parse(input: string | number): string | number {
return typeof input === "string" ? Number(input) : String(input);
}
// this parameter (premier param, effacΓ© Γ la compilation)
function onClick(this: HTMLButtonElement, e: Event) {
this.disabled = true;
}
// Assertion functions
function assertDefined<T>(val: T): asserts val is NonNullable<T> {
if (val == null) throw new Error("Expected defined");
}
// Generic function
function first<T>(arr: T[]): T | undefined { return arr[0]; }7
Classes
TS
class User {
// Modificateurs d'accès
public name: string; // dΓ©faut, accessible partout
private _email: string; // accessible seulement dans cette classe
protected role: string; // accessible dans cette classe + sous-classes
readonly id: number; // lecture seule après construction
// Parameter properties (raccourci)
constructor(
public name: string,
private _email: string,
readonly id: number,
) {}
// Getter / Setter
get email(): string { return this._email; }
set email(val: string) {
if (!val.includes("@")) throw new Error("Invalid");
this._email = val;
}
// MΓ©thode statique
static create(name: string): User { ... }
}
// Implements β une classe satisfait une interface
interface Serializable { toJSON(): string; }
class Model implements Serializable {
toJSON() { return JSON.stringify(this); }
}
// Abstract class
abstract class Shape {
abstract area(): number; // doit Γͺtre implΓ©mentΓ©
describe() { return `Area: ${this.area()}`; }
}
class Circle extends Shape {
constructor(private r: number) { super(); }
area() { return Math.PI * this.r ** 2; }
}8
Generics
TS
// ββ Fonction gΓ©nΓ©rique ββ
function identity<T>(val: T): T { return val; }
identity<string>("hello"); // explicite
identity(42); // infΓ©rΓ© β T = number
// ββ Contraintes (extends) ββ
function getLength<T extends { length: number }>(x: T): number {
return x.length;
}
// ββ Plusieurs paramΓ¨tres ββ
function merge<A, B>(a: A, b: B): A & B {
return { ...a, ...b };
}
// ββ Generic avec keyof ββ
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
// ββ Interface gΓ©nΓ©rique ββ
interface Repository<T> {
findById(id: string): Promise<T | null>;
save(entity: T): Promise<T>;
delete(id: string): Promise<void>;
}
// ββ Classe gΓ©nΓ©rique ββ
class Stack<T> {
private items: T[] = [];
push(item: T) { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
}
// ββ Default type parameter ββ
type ApiRes<T = unknown> = { data: T; status: number };9
Type Guards & Narrowing
TS
// typeof
if (typeof x === "string") { x.toUpperCase(); }
// instanceof
if (err instanceof TypeError) { err.message; }
// in operator
if ("email" in user) { user.email; }
// Discriminated union (switch sur le discriminant)
switch (shape.kind) { ... }
// Truthiness
if (user.name) { /* string (pas undefined, pas "") */ }
// Custom type guard (type predicate)
function isString(val: unknown): val is string {
return typeof val === "string";
}
// Assertion function
function assertNonNull<T>(val: T): asserts val is NonNullable<T> {
if (val == null) throw new Error("Null!");
}
// Non-null assertion (!) β Γ Γ©viter si possible
const el = document.getElementById("app")!; // ! = "trust me, not null"
// as (type assertion) β Γ©viter aussi
const input = el as HTMLInputElement;
// Exhaustive check
function assertNever(x: never): never {
throw new Error(`Unexpected: ${x}`);
}10
Mapped Types
TS
// Syntaxe : { [K in Keys]: Type }
// Tout optionnel
type MyPartial<T> = { [K in keyof T]?: T[K] };
// Tout readonly
type MyReadonly<T> = { readonly [K in keyof T]: T[K] };
// Modifier les modificateurs (+ / -)
type Mutable<T> = { -readonly [K in keyof T]: T[K] };
type Required<T> = { [K in keyof T]-?: T[K] };
// Renommer les clΓ©s (as)
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
// { getName: () => string; getAge: () => number; }
// Filtrer les clΓ©s
type OnlyStrings<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K]
};
// keyof
type UserKeys = keyof User; // "name" | "email" | "age"
// Indexed access
type NameType = User["name"]; // string
type AllValues = User[keyof User]; // string | number11
Conditional Types
TS
// Syntaxe : T extends U ? X : Y
type IsString<T> = T extends string ? true : false;
IsString<string> // true
IsString<number> // false
// Distribution sur les unions
type ToArray<T> = T extends any ? T[] : never;
ToArray<string | number> // string[] | number[]
// EmpΓͺcher la distribution
type ToArray<T> = [T] extends [any] ? T[] : never;
ToArray<string | number> // (string | number)[]
// infer β extraire un type dans un conditionnel
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Flatten<T> = T extends (infer U)[] ? U : T;
Flatten<string[]> // string
Flatten<number> // number
// Unwrap Promise
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;12
Template Literal Types
TS
type EventName = `on${Capitalize<"click" | "focus" | "blur">}`;
// "onClick" | "onFocus" | "onBlur"
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type Endpoint = `/${string}`;
type Route = `${HTTPMethod} ${Endpoint}`;
// Intrinsic string types
Uppercase<"hello"> // "HELLO"
Lowercase<"HELLO"> // "hello"
Capitalize<"hello"> // "Hello"
Uncapitalize<"Hello"> // "hello"
// Pattern matching avec infer
type ExtractParams<T> = T extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractParams<Rest>
: T extends `${string}:${infer Param}`
? Param
: never;
ExtractParams<"/users/:id/posts/:postId"> // "id" | "postId"13
Utility Types (built-in)
| Type | Description | Exemple |
|---|---|---|
| Partial<T> | Toutes les props optionnelles | Partial<User> |
| Required<T> | Toutes les props obligatoires | Required<Config> |
| Readonly<T> | Toutes les props en lecture seule | Readonly<State> |
| Record<K, V> | Objet avec clΓ©s K, valeurs V | Record<string, number> |
| Pick<T, K> | Garde seulement les clΓ©s K | Pick<User, "name" | "email"> |
| Omit<T, K> | Exclut les clΓ©s K | Omit<User, "password"> |
| Exclude<T, U> | Retire U de l'union T | Exclude<"a"|"b"|"c", "a"> β "b"|"c" |
| Extract<T, U> | Garde seulement U de T | Extract<string|number, string> β string |
| NonNullable<T> | Retire null et undefined | NonNullable<string|null> β string |
| ReturnType<T> | Type de retour d'une fonction | ReturnType<typeof fn> |
| Parameters<T> | Tuple des paramètres | Parameters<typeof fn> |
| ConstructorParameters<T> | Params du constructeur | ConstructorParameters<typeof Date> |
| InstanceType<T> | Type d'instance d'une classe | InstanceType<typeof User> |
| Awaited<T> | Unwrap Promise rΓ©cursivement | Awaited<Promise<string>> β string |
| NoInfer<T> | EmpΓͺche l'infΓ©rence (TS 5.4) | NoInfer<T> |
14
Infer & Advanced Patterns
TS
// Deep Partial
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]
};
// Deep Readonly
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K]
};
// Branded types (type nominal)
type Brand<T, B> = T & { __brand: B };
type UserId = Brand<string, "UserId">;
type OrderId = Brand<string, "OrderId">;
// UserId et OrderId ne sont pas interchangeables
// Builder pattern typΓ©
type Builder<T, Built = {}> = {
set<K extends keyof T>(key: K, val: T[K]): Builder<T, Built & Record<K, T[K]>>;
build(): Built;
};
// Extract function argument types at position
type FirstArg<T> = T extends (first: infer A, ...rest: any[]) => any ? A : never;
// Variadic tuples
type Concat<A extends any[], B extends any[]> = [...A, ...B];
Concat<[1, 2], [3, 4]> // [1, 2, 3, 4]15
Modules & Namespaces
TS
// ββ ESM (standard, prΓ©fΓ©rer) ββ
export interface User { name: string; }
export type ID = string;
export const PI = 3.14;
// Import de type uniquement (tree-shakeable)
import type { User, ID } from "./models";
import { type User, createUser } from "./models"; // inline type import
// ββ Namespaces (legacy, Γ©viter dans les nouveaux projets) ββ
namespace Validation {
export interface Validator { validate(s: string): boolean; }
}
// ββ Module augmentation ββ
declare module "express" {
interface Request {
user?: User;
}
}
// ββ Global augmentation ββ
declare global {
interface Window { analytics: Analytics; }
}16
Decorators (TS 5.0+)
TS
// ββ Stage 3 Decorators (TS 5.0+, standard TC39) ββ
function log(target: any, context: ClassMethodDecoratorContext) {
const name = String(context.name);
return function(this: any, ...args: any[]) {
console.log(`Calling ${name}`);
return target.call(this, ...args);
};
}
class Service {
@log
getData() { return "data"; }
}
// Class decorator
function sealed(target: Function, _ctx: ClassDecoratorContext) {
Object.seal(target);
Object.seal(target.prototype);
}
@sealed
class MyClass { ... }
// Cible des decorators : classes, methods, accessors, fields, auto-accessors17
Declaration Files (.d.ts)
TS
// ββ Fichier .d.ts β types pour des libs JS sans types ββ
// DΓ©clarer un module
declare module "my-lib" {
export function doStuff(x: string): number;
export interface Config { debug: boolean; }
export default class Client {
constructor(config: Config);
}
}
// Wildcard module (CSS, images, etc.)
declare module "*.css" {
const content: Record<string, string>;
export default content;
}
declare module "*.png" {
const src: string;
export default src;
}
// Variables globales
declare const __VERSION__: string;
declare function gtag(...args: any[]): void;
// @types/xxx β types DefinitelyTyped (npm)
// npm install @types/node @types/react18
tsconfig.json
JSON
{
"compilerOptions": {
// ββ Target & Module ββ
"target": "ES2022", // version JS de sortie
"module": "NodeNext", // système de modules
"moduleResolution": "NodeNext",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
// ββ Strict (tout activer)
"strict": true, // active toutes les vΓ©rifs strictes
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
// ββ Output ββ
"outDir": "./dist",
"rootDir": "./src",
"declaration": true, // génère .d.ts
"sourceMap": true,
"declarationMap": true,
// ββ Interop ββ
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true, // requis pour Vite/esbuild
"verbatimModuleSyntax": true, // TS 5.0+
// ββ Paths ββ
"baseUrl": ".",
"paths": { "@/*": ["src/*"] },
"skipLibCheck": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}19
TS 5.x NouveautΓ©s
TS 5.0 β 5.5
// ββ TS 5.0 ββ
// β’ Decorators (TC39 stage 3)
// β’ const type parameters
function asConst<const T>(val: T): T { return val; }
asConst([1, 2, 3]); // readonly [1, 2, 3] au lieu de number[]
// β’ satisfies operator
const cfg = { port: 3000 } satisfies Record<string, number>;
// ββ TS 5.1 ββ
// β’ Easier implicit returns for undefined
// β’ Unrelated types for getters/setters
// ββ TS 5.2 ββ
// β’ using (Explicit Resource Management)
{
using file = openFile("data.txt");
// file[Symbol.dispose]() appelΓ© automatiquement Γ la sortie du bloc
}
// β’ Decorator metadata
// ββ TS 5.3 ββ
// β’ Import attributes
import data from "./data.json" with { type: "json" };
// ββ TS 5.4 ββ
// β’ NoInfer<T> β empΓͺche l'infΓ©rence sur un paramΓ¨tre
function createStore<T>(initial: T, allowed: NoInfer<T>[]) { ... }
// β’ Narrowing amΓ©liorΓ© dans les closures
// ββ TS 5.5 ββ
// β’ Inferred type predicates
// β’ Regular expression syntax checking
// β’ Isolated declarations20
Bonnes pratiques
Conseils
// β
Activer "strict": true dans tsconfig
// β
PrΓ©fΓ©rer unknown Γ any
// β
Utiliser les discriminated unions pour le state
// β
PrΓ©fΓ©rer interface pour les objets, type pour les unions/intersections
// β
Utiliser as const pour les constantes littΓ©rales
// β
satisfies pour valider sans widener
// β
import type pour les imports de type uniquement
// β
Type guards custom pour le narrowing complexe
// β
Exhaustive checks avec never dans les switch
// β
Readonly<T> pour les donnΓ©es immutables
// β
Branded types pour les IDs (UserId vs OrderId)
// β
Zod / Valibot pour la validation runtime + infΓ©rence de type
// β any partout β dΓ©sactive tout le bΓ©nΓ©fice de TS
// β as Type (assertions) quand un type guard est possible
// β Non-null assertion (!) sans Γͺtre sΓ»r
// β @ts-ignore sans commentaire explicatif
// β Enums numΓ©riques β prΓ©fΓ©rer string enums ou unions
// β Namespaces dans les projets modernes β utiliser ESM
// β Oublier noUncheckedIndexedAccess (arrays, records)
// β Types trop complexes qui nuisent Γ la lisibilitΓ©TypeScript Cheatsheet Complet β TS 5.x β 2026