Contrairement à de nombreux langages orientés objets, TypeScript met en œuvre une typage structurel (duck typing) : un objet est considéré comme correspondant à un type s'il a toutes les propriétés nécessaires, indépendamment de son (non) déclaration explicite de ce type.
Cette flexibilité peut parfois conduire à des acceptations inattendues d'objets pour un type, si la structure correspond, même s'ils ne sont en fait pas liés en termes de sens. Cela est dangereux dans des modèles de données complexes où la correspondance de la structure est accidentelle.
Structurez toujours correctement les types d'objets, minimisez les correspondances de structure entre différentes entités, pour les cas critiques, utilisez des propriétés ou des symboles supplémentaires pour la « nominalisation » des types.
Exemple de code :
interface Point { x: number; y: number; } interface Pixel { x: number; y: number; } function drawPoint(p: Point) { console.log(p.x, p.y); } const pixel: Pixel = { x: 1, y: 2 }; drawPoint(pixel); // OK, les types sont structurellement compatibles
Caractéristiques clés :
Si la structure de deux interfaces coïncide, cela signifie-t-il qu'elles sont entièrement interchangeables ?
Peut-être sur le plan de la structure, mais pas sur le plan de la logique du programme. Cela est acceptable au niveau du compilateur, mais peut entraîner des erreurs logiques (par exemple, Point et Pixel ci-dessus).
Peut-on interdire la compatibilité structurelle pour un certain type ?
Pas complètement, mais on peut ajouter une propriété unique (par exemple, avec un symbole) :
interface Brand { _brand: unique symbol; }
Désormais, un autre objet ne pourra pas imiter ce type sans le même symbole unique.
En quoi la typage structurelle diffère-t-elle de la typage nominale ?
La structure est basée sur la présence de la structure, la nominale sur la correspondance du nom du type dans un espace de noms donné. Dans TS, le typage est toujours structurel par défaut.
Dans plusieurs entités, les champs se sont coïncidés involontairement (par exemple, User et Admin comme {id: number, name: string}), ce qui a conduit à de la confusion lors du travail avec des contrats API.
Avantages :
Inconvénients :
Utilisation de « marqueurs » uniques symboliques et de champs non standard pour délimiter des types sémantiquement différents avec une structure identique.
Avantages :
Inconvénients :