Les propriétés optionnelles dans TypeScript sont indiquées par un point d'interrogation (?) après le nom de la propriété. Cela signifie que la propriété peut être soit définie, soit absente dans l'objet. C'est pratique pour décrire des structures où tous les champs ne sont pas obligatoires.
Exemple:
interface User { id: number; name?: string; } const u1: User = { id: 1 }; // OK const u2: User = { id: 2, name: 'Ivan' }; // OK
Subtilités:
undefined, mais totalement absente de l'objet.if (user.name)) ne distingue pas undefined de l'absence.undefined et d'appeler des méthodes/propriétés sans vérification.Pour se protéger :
undefined :if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
console.log(user.name?.toUpperCase());
Si un objet est décrit par l'interface
{ foo?: string }, la propriétéfoopeut-elle toujours être uniquement une chaîne ouundefined? Peut-on y assigner, par exemple, la valeurnull?
Mauvaise réponse:
undefined, rien d'autre."Bonne réponse:
null, TypeScript le permet, mais uniquement si le type est élargi à string | null. Par défaut, seul string ou undefined est autorisé.interface A { foo?: string } let x: A = { foo: null }; // Erreur !
Histoire
Dans un grand projet, une partie des objets arrivait du serveur sans certains champs optionnels. Un programmeur appelait directement des méthodes sur ces propriétés (par exemple, toLowerCase()), ce qui entraînait des erreurs d'exécution si le champ était absent. Pour résoudre le problème, l'équipe a implémenté des vérifications strictes et des règles de linter pour l'accès aux champs optionnels.
Histoire
Dans des expressions logiques, on confondait la présence de la propriété et sa véracité : if (user.email) ne fonctionnait pas pour des chaînes vides, bien que la propriété soit définie. Cela a causé un bogue, entraînant la non-envoi de certaines notifications aux utilisateurs.
Histoire
L'équipe a décidé d'assigner la valeur null à une propriété optionnelle, pensant que c'était correct. TypeScript a généré une erreur, et pour contourner cela, il a fallu élargir le type à string | null, ce qui a nécessité une révision de toute la logique métier relative à ces objets.