Historia del tema:
El tipo Symbol fue añadido en JavaScript (ES6) para crear identificadores únicos que, garantizados, no coincidirán con otras propiedades de un objeto. TypeScript admite símbolos desde la inclusión de la compatibilidad con ES6.
Problema:
Antes de la llegada de Symbol, las cadenas se utilizaban a menudo como claves para las propiedades de los objetos. Esto conducía a errores al ampliar o reutilizar objetos: colisiones de nombres aleatorias y la imposibilidad de ocultar propiedades privadas (incluso mediante convenciones). Symbol permitió crear claves únicas e invisibles para el código externo, pero surgieron preguntas sobre la tipificación: ¿cómo describir los tipos con claves Symbol y usarlos de manera segura en la API?
Solución:
TypeScript admite símbolos como valores y tipos, sin embargo, la tipificación de claves Symbol tiene sus particularidades. Para crear un símbolo se puede usar un constructor global o un registro global de símbolos. En las interfaces o tipos, las claves con símbolos deben indicar el tipo como symbol, y el acceso a tales propiedades solo se realiza con una referencia guardada al Symbol.
Ejemplo de código:
const SECRET = Symbol('secret'); interface SecretObject { [SECRET]: string; visible: string; } const obj: SecretObject = { visible: 'mírame', [SECRET]: 'oculto', }; console.log(obj.visible); // 'mírame' // console.log(obj["secret"]); // Error: ¡no existe tal propiedad! console.log(obj[SECRET]); // 'oculto'
Características clave:
¿Puede Symbol convertirse automáticamente en cadena al usarse en objetos?
No, Symbol no se puede convertir automáticamente en una cadena, intentar hacerlo (por ejemplo, mediante concatenación) dará lugar a un error.
const mySymbol = Symbol('desc'); // alert('prefijo_' + mySymbol); // TypeError
¿Se pueden enumerar claves Symbol a través de Object.keys?
No, Object.keys y for...in ignoran las claves Symbol. Para obtener tales claves se utiliza Object.getOwnPropertySymbols.
const sym = Symbol('a'); const obj = { [sym]: 42 }; Object.keys(obj); // [] Object.getOwnPropertySymbols(obj); // [Symbol(a)]
¿Se pasan propiedades con claves Symbol al copiar a través de Object.assign?
Sí, Object.assign copia tanto claves de cadena como simbólicas, a diferencia de JSON.stringify.
const s = Symbol('s'); const o1 = { [s]: 123, foo: 'bar' }; const o2 = Object.assign({}, o1); o2[s]; // 123
Un desarrollador utilizó claves de cadena para propiedades privadas ('_private'), confiando en la convención. En el Equipo B, accidentalmente se añadió la misma cadena — las propiedades se sobrescribieron, resultando en un error inesperado.
Pros:
Contras:
Un segundo desarrollador utilizó Symbol para propiedades ocultas (por ejemplo, Symbol('internal')). Ahora, incluso dentro del equipo, no se pueden sobrescribir accidentalmente los datos internos: el acceso solo es posible si se tiene una referencia al Symbol específico.
Pros:
Contras: