TypeScript : objets, interfaces et fonctions
Décrire un objet
Section intitulée « Décrire un objet »interface Client { id: number; nom: string; email?: string; // facultative readonly creeLe: Date; // non modifiable après création}
const alice: Client = { id: 1, nom: 'Alice', creeLe: new Date() };alice.nom = 'Alice Martin'; // autoriséalice.creeLe = new Date(); // erreur : propriété en lecture seuleÉquivalent avec type :
type ClientType = { id: number; nom: string; email?: string; readonly creeLe: Date;};interface ou type ?
Section intitulée « interface ou type ? »interface |
type |
|
|---|---|---|
| Décrire un objet | Oui | Oui |
| Étendre | extends (lisible) |
Intersection & |
| Fusion de déclarations (même nom déclaré deux fois) | Oui | Non (erreur) |
| Unions, tuples, littéraux, types calculés | Non | Oui |
Implémentée par une classe (implements) |
Oui | Oui (pour un objet) |
Règle simple : interface pour décrire la forme d’un objet ou d’une classe, type pour tout le reste (unions, tuples, types dérivés). Le plus important est d’être cohérent dans un projet.
Extension et composition
Section intitulée « Extension et composition »interface Personne { nom: string; email: string;}interface Employe extends Personne { poste: string;}
type Identifie = { id: number };type ClientComplet = Personne & Identifie; // intersection
const e: Employe = { nom: 'Alice', email: 'alice@exemple.com', poste: 'Développeuse',};extends signale une erreur si une propriété est incompatible ; l’intersection & produit un type difficile à lire si les propriétés se contredisent (résultat never).
Signatures d’index
Section intitulée « Signatures d’index »Pour des objets dont les clés ne sont pas connues à l’avance :
interface Dictionnaire { [cle: string]: number;}const notes: Dictionnaire = { alice: 15, bob: 12 };
const stocks: Record<string, number> = { a: 3 }; // équivalent plus lisibleconst roles: Record<'admin' | 'editeur', string[]> = { admin: [], editeur: [] };Avec noUncheckedIndexedAccess, notes['alice'] vaut number | undefined. Pour un ensemble de clés connues, Record<Union, T> oblige à toutes les fournir.
Propriétés excédentaires
Section intitulée « Propriétés excédentaires »interface Options { port: number;}
const options: Options = { port: 3000, hote: 'local' }; // erreur : propriété inconnue « hote »const brut = { port: 3000, hote: 'local' };const autre: Options = brut; // accepté (pas un littéral direct)La vérification d’excès ne s’applique qu’aux littéraux d’objet passés directement : elle attrape les fautes de frappe.
Fonctions
Section intitulée « Fonctions »function additionner(a: number, b: number): number { return a + b;}
const multiplier = (a: number, b: number): number => a * b;
type Operation = (a: number, b: number) => number;const soustraire: Operation = (a, b) => a - b; // paramètres typés par le contexte
interface Rappel { (erreur: Error | null, resultat?: string): void;}Paramètres facultatifs, par défaut, restants
Section intitulée « Paramètres facultatifs, par défaut, restants »function saluer(nom: string, titre?: string): string { return `${titre ?? ''} ${nom}`.trim();}
function creer(nom: string, actif = true): { nom: string; actif: boolean } { return { nom, actif };}
function somme(...nombres: number[]): number { return nombres.reduce((total, n) => total + n, 0);}Objet d’options
Section intitulée « Objet d’options »Au-delà de trois paramètres, préférer un objet nommé :
interface OptionsRequete { methode?: 'GET' | 'POST'; delaiMs?: number; entetes?: Record<string, string>;}
function requeter( url: string, { methode = 'GET', delaiMs = 5000, entetes = {} }: OptionsRequete = {},) { return { url, methode, delaiMs, entetes };}
requeter('/api', { delaiMs: 1000 });Surcharges
Section intitulée « Surcharges »function lire(valeur: string): string[];function lire(valeur: number): number;function lire(valeur: string | number): string[] | number { return typeof valeur === 'string' ? valeur.split(',') : valeur * 2;}
const a = lire('a,b'); // string[]const b = lire(4); // numberLes surcharges sont utiles mais lourdes : une union de types ou des génériques (Génériques et types utilitaires) suffisent le plus souvent.
Fonctions asynchrones
Section intitulée « Fonctions asynchrones »async function chargerClient(id: number): Promise<Client> { const reponse = await fetch(`/api/clients/${id}`); if (!reponse.ok) throw new Error(`HTTP ${reponse.status}`); return (await reponse.json()) as Client; // à valider en pratique (voir « Projets Node.js et web »)}
const clients: Promise<Client[]> = Promise.all([ chargerClient(1), chargerClient(2),]);Le type de retour d’une fonction async est toujours Promise<…>.
this dans les fonctions
Section intitulée « this dans les fonctions »interface Compteur { n: number; incrementer(this: Compteur): void;}
const c: Compteur = { n: 0, incrementer() { this.n += 1; },};Le paramètre factice this documente et vérifie le contexte d’appel (détails dans POO : classes et objets).
Types dérivés d’une valeur
Section intitulée « Types dérivés d’une valeur »const defauts = { port: 3000, hote: '127.0.0.1' };type Defauts = typeof defauts; // { port: number; hote: string }
function creerClient(nom: string) { return { id: 1, nom };}type ClientCree = ReturnType<typeof creerClient>; // { id: number; nom: string }Dériver les types depuis le code réel évite de les maintenir en double.
Dépannage
Section intitulée « Dépannage »| Symptôme | Piste |
|---|---|
Object literal may only specify known properties |
Propriété inconnue (souvent une faute de frappe) : corriger ou étendre l’interface |
Type '{ … }' is missing the following properties |
Propriété obligatoire absente |
Cannot assign to 'x' because it is a read-only property |
Propriété readonly : créer un nouvel objet |
Index signature for type 'string' is missing |
Objet sans signature d’index utilisé comme dictionnaire |
This expression is not callable (union de fonctions) |
Signatures incompatibles : affiner d’abord |
A rest parameter must be of an array type |
...args doit être un tableau (string[]) |
Type instantiation is excessively deep |
Types récursifs trop complexes : simplifier |
Ubuntu 24.04 et 26.04 : différences à connaître
Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »Aucune.