Historique de la question :
Le type Symbol a été ajouté à JavaScript (ES6) pour créer des identifiants uniques qui ne coïncident jamais avec d'autres propriétés d'objet. TypeScript prend en charge les symboles depuis l'inclusion de la compatibilité ES6.
Problème :
Avant l'apparition de Symbol, les chaînes étaient souvent utilisées comme clés pour les propriétés des objets. Cela a conduit à des erreurs lors de l'extension ou de la réutilisation des objets : collisions de noms aléatoires et impossibilité de cacher les propriétés privées (même par convention). Symbol a permis de créer des clés uniques, invisibles au code externe, mais des questions de typage se sont posées : comment décrire les types avec des clés Symbol et les utiliser en toute sécurité dans une API ?
Solution :
TypeScript prend en charge les symboles en tant que valeurs et types, cependant, le typage des clés Symbol a ses particularités. Pour créer un symbole, on peut utiliser le constructeur global ou le registre global des symboles. Dans les interfaces ou types, les clés avec des symboles doivent explicitement indiquer le type comme symbol, et l'accès à ces propriétés se fait uniquement avec une référence conservée sur le Symbol.
Exemple de code :
const SECRET = Symbol('secret'); interface SecretObject { [SECRET]: string; visible: string; } const obj: SecretObject = { visible: 'see me', [SECRET]: 'hidden', }; console.log(obj.visible); // 'see me' // console.log(obj["secret"]); // Erreur : cette propriété n'existe pas ! console.log(obj[SECRET]); // 'hidden'
Caractéristiques clés :
Un Symbol peut-il être automatiquement converti en chaîne lors de son utilisation dans des objets ?
Non, un Symbol ne peut pas être automatiquement converti en chaîne, toute tentative de le faire (par exemple, via la concaténation) entraînera une erreur.
const mySymbol = Symbol('desc'); // alert('prefix_' + mySymbol); // TypeError
Peut-on énumérer des clés Symbol via Object.keys ?
Non, Object.keys et for...in ignorent les clés Symbol. Pour obtenir ces clés, on utilise Object.getOwnPropertySymbols.
const sym = Symbol('a'); const obj = { [sym]: 42 }; Object.keys(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(a)]
Les propriétés avec des clés Symbol sont-elles transmises lors de la copie via Object.assign ?
Oui, Object.assign copie à la fois les clés de chaîne et les clés symboliques, contrairement à JSON.stringify.
const s = Symbol('s'); const o1 = { [s]: 123, foo: 'bar' }; const o2 = Object.assign({}, o1); o2[s]; // 123
Un développeur a utilisé des clés de chaîne pour les propriétés privées ('_private'), en se fiant à la convention. L'équipe B a accidentellement ajouté une chaîne identique — les propriétés ont été écrasées, ce qui a causé une erreur imprévisible.
Avantages :
Inconvénients :
Un deuxième développeur a utilisé Symbol pour les propriétés cachées (par exemple, Symbol('internal')). Maintenant, même au sein de l'équipe, il n'est pas possible d'écraser accidentellement les données internes : l'accès n'est possible que si l'on a une référence au Symbol spécifique.
Avantages :
Inconvénients :