Enumerations syntactic sugar

Common syntax:

enum Roles { ADMIN, MEMBER, GUEST }

// Equivalent to...
const Roles = new Object;
Object.defineProperty(Roles, 'ADMIN', { enumerable: true, value: Symbol('ADMIN') });
Object.defineProperty(Roles, 'MEMBER', { enumerable: true, value: Symbol('MEMBER') });
Object.defineProperty(Roles, 'GUEST', { enumerable: true, value: Symbol('GUEST') });

With set values:

enum Colors { RED: 0xff0000, GREEN: 0x00ff00, BLUE: 0x0000ff }

// Equivalent to...
const Colors = new Object;
Object.defineProperty(Colors, 'RED', { enumerable: true, value: 0xff0000 });
Object.defineProperty(Colors, 'GREEN', { enumerable: true, value: 0x00ff00 });
Object.defineProperty(Colors, 'BLUE', { enumerable: true, value: 0x0000ff });

Maybe with a syntax for supplying a generator function to define the enumerators?:

function* bitField(target) {
  let place = 0;
  while(true) {
    const [key, value] = yield;
    Object.defineProperty(target, key, { enumerable: true, value: 2 ** place++ });
  }
}

enum Permissions with bitField { READ, SEND, DELETE, BLOCK }

// Equivalent to...
const Permissions = new Object;
Object.defineProperty(Permissions, 'READ', { enumerable: true, value: 1 });
Object.defineProperty(Permissions, 'SEND', { enumerable: true, value: 2 });
Object.defineProperty(Permissions, 'DELETE', { enumerable: true, value: 4 });
Object.defineProperty(Permissions, 'BLOCK', { enumerable: true, value: 8 });

And a simple practical example:

enum Roles { ADMIN, WRITER, EDITOR, SUBSCRIBER, GUEST }

class User {
    #role = Roles.GUEST;
    setRole(role) { this.#role = role }
    canEdit() {
        switch(this.#role) {
            case Roles.ADMIN:
            case Roles.WRITER:
            case Roles.EDITOR:
                return true;
            default:
                return false;
        }
    }
}

See https://github.com/rwaldron/proposal-enum-definitions and https://github.com/rbuckton/proposal-enum

1 Like

i don't think enums have compelling use-cases in javascript. the scenarios given are just-as-effectively solved with plain-dictionary or strings, that have less tech-debt:

/*
 * if interfacing with external hardware/api with predefined-enums,
 * a plain dictionary is more elegant.
 */
var samsungLcdEnum = {
    "RED": 0xff0000,
    "GREEN": 0x00ff00,
    "BLUE": 0x0000ff
};
...
switch (hardwareInput.color) {
case samsungLcdEnum.RED:
    ...
    break;
case samsungLcdEnum.GREEN:
    ...
    break;
case samsungLcdEnum.BLUE:
    ...
    break;
}



/*
 * for all other scenarios,
 * vanilla-strings are more elegant than [int] enums.
 */
var middlewareSecurity = function (request, response, next) {
    var requestBody = ... // e.g. { "role": "ADMIN" }
    switch (requestBody.role) {
    case "ADMIN":
        ...
        break;
    case "MEMBER":
        ...
        break;
    case "GUEST":
        ...
        break;
    default:
        response.statusCode = 403;
        response.end("Forbidden");
    }
};