Skip to content

Instantly share code, notes, and snippets.

@ramybenaroya
Forked from xmlking/Enum.es6.js
Last active September 23, 2020 10:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ramybenaroya/23e42b8b7840965bbd54 to your computer and use it in GitHub Desktop.
Save ramybenaroya/23e42b8b7840965bbd54 to your computer and use it in GitHub Desktop.
JavaScript Enums with ES6, Type Checking, Immutability and dynamic public methods
/*eslint-disable */
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/*eslint-enable */
function getEnumClass(options = {}, _EnumSymbol){
function EnumClass() {
_classCallCheck(this, EnumClass);
_EnumSymbol.apply(this, arguments);
}
_inherits(EnumClass, _EnumSymbol);
Object.keys(options).
filter((key) => {
return key !== 'literals' && typeof options[key] === 'function';
})
.forEach((key) => {
EnumClass.prototype[key] = options[key];
});
return EnumClass;
}
export class EnumSymbol {
constructor(name, keys = {}) {
Object.keys(keys).forEach((key) => {
this[key] = keys[key];
this.sym = Symbol.for(name);
});
Object.freeze(this);
}
toString() {
return this.sym;
}
valueOf() {
return this.value;
}
}
export default class Enum {
constructor(options = {}) {
let {literals} = options;
var EnumClass = getEnumClass(options, EnumSymbol);
for (let key in literals) {
if(!literals[key]) {
throw new TypeError('each enum should have been initialized with at least empty {} value');
}
this[key] = new EnumClass(key, literals[key]);
}
Object.freeze(this);
}
symbols() {
return this.keys().map((key) => this[key]);
}
keys() {
return Object.keys(this).filter((key) => this[key] instanceof EnumSymbol);
}
contains(sym) {
if (!(sym instanceof EnumSymbol)) {
return false;
}
return this[Symbol.keyFor(sym.sym)] === sym;
}
}
import Enum from './Enum';
var assert = require("assert")
describe('Module 1', function() {
it('it works', function() {
const ReadyState = new Enum({
literals: {
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'}
},
prettyPrint(){
return `value: ${this.value}, description: ${this.description}`;
},
prettierPrint(){
return `The value is ${this.value} and the description is ${this.description}`;
}
});
assert.notEqual(ReadyState.symbols().indexOf(ReadyState.CONNECTING), -1);
assert.notEqual(ReadyState.keys().indexOf('CONNECTING'), -1);
assert.ok(ReadyState.contains(ReadyState.OPEN));
assert.ok(ReadyState.OPEN > ReadyState.CONNECTING);
assert.notEqual(ReadyState.OPEN, ReadyState.CLOSED);
assert.equal(ReadyState.OPEN.description, 'Open');
assert.equal(ReadyState.CONNECTING.prettyPrint(), 'value: 0, description: Connecting');
assert.equal(ReadyState.CONNECTING.prettierPrint(), 'The value is 0 and the description is Connecting');
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment