Aller au contenu

TypeScript : objets, interfaces et fonctions

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

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

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 lisible
const 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.

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.

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;
}
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);
}

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

Les surcharges sont utiles mais lourdes : une union de types ou des génériques (Génériques et types utilitaires) suffisent le plus souvent.

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

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

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.

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.