Skip to content

Instantly share code, notes, and snippets.

@xmlking
Last active June 25, 2019 18:09
Show Gist options
  • Star 61 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save xmlking/e86e4f15ec32b12c4689 to your computer and use it in GitHub Desktop.
Save xmlking/e86e4f15ec32b12c4689 to your computer and use it in GitHub Desktop.
JavaScript Enums with ES6, Type Checking and Immutability
export class EnumSymbol {
sym = Symbol.for(name);
value: number;
description: string;
constructor(name: string, {value, description}) {
if(!Object.is(value, undefined)) this.value = value;
if(description) this.description = description;
Object.freeze(this);
}
get display() {
return this.description || Symbol.keyFor(this.sym);
}
toString() {
return this.sym;
}
valueOf() {
return this.value;
}
}
export class Enum {
constructor(enumLiterals) {
for (let key in enumLiterals) {
if(!enumLiterals[key]) throw new TypeError('each enum should have been initialized with atleast empty {} value');
this[key] = new EnumSymbol(key, enumLiterals[key]);
}
Object.freeze(this);
}
symbols() {
return [for (key of Object.keys(this)) this[key] ];
}
keys() {
return Object.keys(this);
}
contains(sym) {
if (!(sym instanceof EnumSymbol)) return false;
return this[Symbol.keyFor(sym.sym)] === sym;
}
}
//now create your won Enum consts
const [INCREMENTAL, EXPONENTIAL, FIBONACCI] = [{},{},{}];
export const BackoffStrategy = new Enum({INCREMENTAL, EXPONENTIAL, FIBONACCI});
export const ReadyState = new Enum({
CONNECTING: {value: 0, description: 'Connecting'},
OPEN: {value: 1, description: 'Open'},
CLOSING: {value: 2, description: 'Closing'},
CLOSED: {value: 3, description: 'Closed'},
RECONNECT_ABORTED: {value: 4, description: 'Reconnect Aborted'}
});
assert.isTrue(ReadyState.OPEN > ReadyState.CONNECTING)
assert.notEqual(ReadyState.OPEN, ReadyState.CLOSED)
assert.equal(ReadyState.OPEN.description, 'Open')
assert.equal(BackoffStrategy.INCREMENTAL.display, 'INCREMENTAL')
@jvmlet
Copy link

jvmlet commented Jan 12, 2016

Hi
Does it make sense to add valueOf(name) to Enum:

valueOf(name){
 const foundSymbol = this.symbols.find(sym=>(name == Symbol.keyFor(sym)));
 if(Object.is(foundSymbol , undefined)){
  throw new Error(name +' doesn't belong to this Enum')
 }
 return foundSymbol ;
}

@mprokopowicz
Copy link

What does symbols() method does?

@LuanNunes
Copy link

Fix this, please:

symbols() {
const result = [];
for (let key of Object.keys(this)) result.push(this[key]);

return result;

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment