Skip to content

Instantly share code, notes, and snippets.

@eliasfeijo
Last active June 24, 2022 07:59
Show Gist options
  • Save eliasfeijo/0b1286a88faef97e752dcb72f925cbee to your computer and use it in GitHub Desktop.
Save eliasfeijo/0b1286a88faef97e752dcb72f925cbee to your computer and use it in GitHub Desktop.
Javascript function to replace an object's symbol keys with equivalent string keys
// Typescript version: https://gist.github.com/eliasfeijo/672c83ff971653b551e168b156bb3baf
// Symbol used to make "_perform" method pseudo-private
const _perform = Symbol('_perform');
class SymbolKeysToStringTask {
constructor() {
this.symbolCounter = 0;
}
[_perform](o) {
const isArray = o.constructor === Array;
const newObject = isArray ? o : {};
Reflect.ownKeys(o).forEach(key => {
// if (isArray === true && key is NaN) means that it is an internal property of array e.g., "length", we won't collect those
if (isArray && isNaN(Number(key))) return;
const value = isArray ? o[Number(key)] : o[key];
let parsedKey = key;
if (typeof key === 'symbol') {
if (key.description) parsedKey = key.description;
else {
parsedKey = `_symbol${++this.symbolCounter}`;
}
}
if (value !== null && typeof value === 'object') {
newObject[parsedKey] = this[_perform](value);
return;
}
newObject[parsedKey] = value;
});
return newObject;
}
static run(o) {
const task = new SymbolKeysToStringTask();
return task[_perform](o);
}
}
// Usage:
const myObject = {
// Accepts numeric keys
1: 'some value',
// Accepts string keys
stringKey: 'another value',
// Using Symbol.for(keyName)
[Symbol.for('KEY_A')]: 'A',
// Using Symbol(keyName)
[Symbol('KEY_B')]: 'B',
// Using Symbol()
[Symbol()]: 1,
[Symbol()]: 2,
// Using Symbol() with nested objects and arrays
[Symbol()]: {
[Symbol()]: 'inside nested object',
[Symbol()]: [{ [Symbol()]: 'inside nested array' }],
},
};
const newObject = SymbolKeysToStringTask.run(myObject);
console.log(newObject);
/* Output
* {
* "1": "some value",
* "stringKey": "another value",
* "KEY_A": "A",
* "KEY_B": "B",
* "_symbol1": 1,
* "_symbol2": 2,
* "_symbol3": {
* "_symbol4": "inside nested object",
* "_symbol5": [
* {
* "_symbol6": "inside nested array"
* }
* ]
* }
* }
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment