A More Idiomatic Enum for JavaScript

A More Idiomatic Enum for JavaScript

  • Idiomatic to JavaScript
  • Semantic
  • Progressive
  • Arbitrary value types
  • Mergeable
  • Straightforward desugaring
  • Straightforward TypeScript typing

Basic Syntax

enum STATUS {
    Ready: 0,
    Pending: 1,
    Done: 2
};

Desugaring: Object + (1. Pure syntactic sugar OR 2. Frozen object)

// Option 1: Pure syntactic sugar (for readability)
const STATUS = {
    Ready: 0,
    Pending: 1,
    Done: 2,
};
// Option 2: Frozen object (with runtime immutability)
const STATUS = Object.freeze({
    Ready: 0,
    Pending: 1,
    Done: 2,
});

Arbitrary Value Types

enum STATUS {
    Ready: 0,
    Pending: "pending",
    Done: true,
    Error: null,
    Warn: {}
}

Merging: {...enum, ...object}

enum APP_STATUS {
    Ready: "ready",
    Pending: "pending",
    Done: "done"
}

enum USER_STATUS {
    LoggedIn: "logged-in",
    LoggedOut: "logged-out"
}

const TEST_STATUS = {
    Success: "success",
    Error: "error"
};

enum STATUS {
    ...APP_STATUS,
    ...USER_STATUS,
    ...TEST_STATUS
}

Design Rationale: No Reverse Mapping

The decision to omit reverse mapping is a deliberate choice to keep the feature idiomatic to JavaScript.

  • Idiomatic & Predictable: JS developers are accustomed to standard object semantics. Adding reverse mapping introduces hidden complexity that breaks the β€œwhat you see is what you get” intuition.
  • Rarely Used: In practice, the need for STATUS[1] is extremely rare compared to STATUS.Ready.
  • Ambiguity with Shared Values: Reverse mapping is fundamentally broken when different keys map to the same value. For example, if Ready: 1 and Success: 1 both exist, a reverse mapping like STATUS[1] is ambiguous. Plain objects naturally handle this by just retaining the key-value structure.

For cases where reverse lookup is strictly necessary, developers can easily and explicitly use Object.entries() or Object.keys() to build a reverse map, paying only for what they actually use.

Hi @yxdtg

There is an existing proposal for enums. If this is an idea on how that proposal could change it would be best to discuss there.

2 Likes

Sure, thanks for the reminder

https://www.npmjs.com/package/@jiaozi-dev/kit

Is a new result type string from typeof desired, or do you propose Enum.isEnum()? Why is the Array add-on solution using Object (that is, just defining a new Prototype) not okay for Enum? Should Enums be only integers, or other datatypes as well? What is lacking in the existing syntax for enumerations as constant object literals declared using {}? Why is a new idiomatic syntax useful? Are you trying to eliminate the need for the awful Object.freeze?

Perhaps my questions are not needed. I see that the existing proposal (link above) answers most of them similarly to TypeScript.