Storia della questione:
Il tipo Symbol è stato aggiunto in JavaScript (ES6) per creare identificatori unici che non si sovrappongano ad altre proprietà dell'oggetto. TypeScript supporta i simboli sin dall'inclusione della compatibilità con ES6.
Problema:
Prima dell'arrivo di Symbol, le stringhe erano spesso utilizzate come chiavi per le proprietà degli oggetti. Ciò portava a errori durante l'estensione o il riutilizzo degli oggetti: collisioni casuali nei nomi e impossibilità di nascondere le proprietà private (anche solo tramite convenzioni). Symbol ha permesso di creare chiavi uniche, invisibili al codice esterno, ma sono sorte domande sulla tipizzazione: come descrivere i tipi con chiavi Symbol e usarli in modo sicuro nelle API?
Soluzione:
TypeScript supporta i simboli come valori e tipi, tuttavia la tipizzazione delle chiavi Symbol ha delle peculiarità. Un simbolo può essere creato usando il costruttore globale o il registro globale dei simboli. Negli interface o nei tipi, le chiavi con simboli devono esplicitamente indicare il tipo come symbol, mentre l'accesso a tali proprietà avviene solo tramite un riferimento salvato al Symbol.
Esempio di codice:
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"]); // Errore: questa proprietà non esiste! console.log(obj[SECRET]); // 'hidden'
Caratteristiche principali:
Può Symbol essere convertito automaticamente in una stringa quando utilizzato negli oggetti?
No, Symbol non può essere convertito automaticamente in una stringa; provare a farlo (ad esempio, tramite concatenazione) genererà un errore.
const mySymbol = Symbol('desc'); // alert('prefix_' + mySymbol); // TypeError
Posso elencare le chiavi Symbol tramite Object.keys?
No, Object.keys e for...in ignorano le chiavi Symbol. Per ottenere tali chiavi si utilizza Object.getOwnPropertySymbols.
const sym = Symbol('a'); const obj = { [sym]: 42 }; Object.keys(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(a)]
Le proprietà con chiavi Symbol vengono trasferite durante la copia tramite Object.assign?
Sì, Object.assign copia sia le chiavi stringa che quelle simboliche, a differenza di JSON.stringify.
const s = Symbol('s'); const o1 = { [s]: 123, foo: 'bar' }; const o2 = Object.assign({}, o1); o2[s]; // 123
Un sviluppatore ha utilizzato chiavi stringa per proprietà private ('_private'), basandosi su convenzioni. Nel Team B è stata accidentalmente aggiunta la stessa stringa: le proprietà si sono sovrapposte, causando un errore imprevedibile.
Pro:
Contro:
Un secondo sviluppatore ha utilizzato Symbol per proprietà nascoste (ad esempio, Symbol('internal')). Ora, anche all'interno del team, non è possibile sovrascrivere accidentalmente i dati interni: l'accesso è possibile solo se si ha un riferimento al Symbol specifico.
Pro:
Contro: