title: ES6 read-only enums that can map value to name
body: <p>I would like to define an enum-like structure in JS, but have two requirements:</p>
  <ol>
  <li>The values be read-only, i.e. no users can assign to them.</li>
  <li>The values (0, 1, 2, ...) can be mapped back into the names (as with Java's <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html#name%28%29" rel="nofollow noreferrer">name method</a>)</li>
  </ol>
  <p>The methods I know to create enums like this typically meet one requirement or the other, not both.</p>
  <p>I've tried:</p>
  <pre><code>const MyEnum = {
    a: 0,
    b: 1,
    c: 2
  };
  </code></pre>
  <p>The enum itself is constant, but the values are still mutable and I can't map values back to names efficiently.</p>
  <p>When writing an <code>enum</code> in Typescript, it outputs:</p>
  <pre><code>var MyEnum;
  (function (MyEnum) {
      MyEnum[MyEnum[&quot;a&quot;] = 0] = &quot;a&quot;;
      MyEnum[MyEnum[&quot;b&quot;] = 1] = &quot;b&quot;;
      MyEnum[MyEnum[&quot;c&quot;] = 2] = &quot;c&quot;;
  })(MyEnum || (MyEnum = {}));
  </code></pre>
  <p>This can map both ways, but still doesn't have constant values.</p>
  <p>The only option I've found that meets both requirements would be using getters on a class:</p>
  <pre><code>class MyEnum {
    get a() {
      return 0;
    }
    ...
  }
  </code></pre>
  <p>This method dramatically restricts the legal names and has a lot of overhead, especially in browsers that don't inline getters well (or can't).</p>
  <p><a href="https://chat.stackoverflow.com/transcript/message/23759314#23759314">@Shmiddty suggested freezing an object</a>:</p>
  <pre><code>const MyEnum = Object.freeze({
    a: 0,
    b: 1,
    c: 2
  });
  </code></pre>
  <p>This meets the constant requirement well, but doesn't provide a great way to map values back to names.</p>
  <p>I could write a helper that builds the reverse mapping like:</p>
  <pre><code>function reverseEnum(enum) {
    Object.keys(enum).forEach(k =&gt; {
      enum[enum[k]] = k;
    });
  }
  </code></pre>
  <p>But any kind of programmatic solution to generate the reverse mapping will run into problems if the original object is frozen or otherwise actually constant.</p>
  <p>Is there a clean, concise solution to this in JS?</p>