Considering a first-class primitive type?
Strings and numbers aren't usually ideal since they don't have the formal typing semantics you usually want from enums.
Symbols work well in having the correct uniqueness property, so form a good recommended "default" for an enum.
The problem is that if you have a symbol of this type, you don't know at a runtime level that it comes from an enum, which enum set it comes from etc etc.
So I was wondering if it's worth considering a first-class primitive type for enumvalue say, which could behave like a symbol, but potentially have some extra features, including:
- The ability to get the enum from the value, for example
enum X { A, B }supporting someX.A.enum === X - The ability to have helper methods like
is:X.A.is(X.A) === true, whileX.A.is(X.B) === false - ADT unwrapping -
enum X { A(), B }to supportX.A(10).unwrap() === 10 - ADT equality support (eg
enum X { A(), B }could be defined to haveEnum.A(5) === Enum.A(5)via the union of equality on its members)
Overall the code style might be closer to what users expect in imperatively operating on enum and ADT enum values.
For example consider the standard case of a Result type supporting simple is checks and unwrap:
enum Result {
Ok(),
Err()
}
const res = operation();
console.log(typeof res); // enumvalue
if (res.is(Result.Ok)) {
return res.unwrap();
} else if (res.is(Result.Err)) {
return res.unwrap();
}
I understand pattern matching also plays a large role here, but having imperative forms also seems useful. Alternatively a lot of these cases could also be handled with the original enum I suppose, but at least being able to get the enum class from the enum value is a useful feature we might not otherwise have.
In the earliest version of https://github.com/rbuckton/proposal-enum I planned to introduce a new typeof tag. However, plenary discussions related to Records and Tuples indicate that most implementers would rather avoid new primitive types due to the high implementation cost. As a result, https://github.com/rbuckton/proposal-enum moved to instead leverage existing primitive types and regular JS objects instead, which also happens to align more closely with the current emit for enums in TypeScript.
However, plenary discussions related to Records and Tuples indicate that most implementers would rather avoid new primitive types due to the high implementation cost.
Agree, it's looks not likely to add a new primitive type although it would be useful.
for example
enum X { A, B }supporting someX.A.enum === X
This is useful but problematic when it is primitive. In JavaScript today, primitives are re-wrapped in each Realm. What will happen when you send X.A to another Realm? It looks like we need to "reconstruct" the enum like it is a built-in primitive constructor (like Boolean or Number) to make X.A.enum work.
X.A(10).unwrap() === 10
This reminds me of the Box in the R&T proposal. I think ADT can be a normal data property like { type: X.A.symbol, value: [10] }.
Enum.A(5) === Enum.A(5)
Implementers look like rejecting this idea (based on what happened to the R&T proposal)...
I still don't get why new primitive type would cause high cost (my impression is engine delegates said new primitive types would have performance penalty in === operations but I don't understand the reasons).
I also have a question about symbol, could shared struct allow to share symbols? It seems structured clone don't allow symbols.
I also don't understand it, but since all the browsers are in agreement, there will be no new primitive types unless they change their minds.
I suspect sharing identity would be a problem, and non-global symbols have identity.