I would like to define an enum-like structure in JS, but have two requirements:
- The values be read-only, i.e. no users can assign to them.
- The values (0, 1, 2, ...) can be mapped back into the names (as with Java's name method)
The methods I know to create enums like this typically meet one requirement or the other, not both.
I've tried:
const MyEnum = {
a: 0,
b: 1,
c: 2
};
The enum itself is constant, but the values are still mutable and I can't map values back to names efficiently.
When writing an enum
in Typescript, it outputs:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["a"] = 0] = "a";
MyEnum[MyEnum["b"] = 1] = "b";
MyEnum[MyEnum["c"] = 2] = "c";
})(MyEnum || (MyEnum = {}));
This can map both ways, but still doesn't have constant values.
The only option I've found that meets both requirements would be using getters on a class:
class MyEnum {
get a() {
return 0;
}
...
}
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).
@Shmiddty suggested freezing an object:
const MyEnum = Object.freeze({
a: 0,
b: 1,
c: 2
});
This meets the constant requirement well, but doesn't provide a great way to map values back to names.
I could write a helper that builds the reverse mapping like:
function reverseEnum(enum) {
Object.keys(enum).forEach(k => {
enum[enum[k]] = k;
});
}
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.
Is there a clean, concise solution to this in JS?
I'd use a Map so that your enum values can be any type, rather than having them coerced into strings.
If your enum is all strings, I'd also probably change one line to:
to ensure that the enum values are being used properly. Using just a string, you have no guarantee that some code hasn't simply passed a normal string that happens to be the same as one of your enum values. If your values are always strings or symbols, you could also swap out the Map for a simple object.