Open mulias opened 6 years ago
@mulias This says that "enums are real objects at runtime" https://www.typescriptlang.org/docs/handbook/enums.html, so I would expect enumDecoder(Directions)
to work. Is that a recent change?
@RocketPuppy I had looked into this a while ago and had forgotten some of the details. The issue I found is that if you define an enum
then it has an object at runtime which can be used to create a decoder, but if you define a const enum
it is removed during compilation. My concern was that it seemed like there was no static warning about using a const enum
as if it existed at runtime, and I didn't want to have special documentation that said "this helper will only work for non-const enums and will otherwise fail at runtime without warning." Maybe I need to re-investigate that option.
I should note that shortly after posting this issue I realized that it's totally possible to write the enum
decoder inside of the Decoder
class defined in this library, but it can't be done as a helper function like I was attempting above.
Ah, I thought it might have been an issue with const enums. You could have two decoders. One that takes an enum object and one that takes enum members. I think Typescript should prevent you from using the const enum with the enum object decoder.
Only one way to find out :)
New issue with enumDecoder(Directions)
Object.keys(Directions)
// [ '0', '1', '2', '3', 'North', 'South', 'East', 'West' ]
Enum runtime objects are implemented as two way mappings, so if all I have is the enum then I can't actually tell which values are the keys.
All the ways around that seem pretty hacky, so I think we're stuck with listing out the enum values.
It appears that the behavior is heavily intended, and is also specific to numeric values for enums.
If the enum uses string values, no reverse mapping happens - so at least for string enums, it becomes possible to make the assumption that you can coerce the enum into an array and use an Array.includes() call to verify if the enum is a member. However, there's no easy way to verify if the enum is a string enum or not, making it something that can only be done by hand.
More info here: https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings Also related: https://github.com/Microsoft/TypeScript/issues/30487
Given a TS enum
We currently write the decoder as
which isn't great.
It's worth noting that the most ideal syntax is not possible, since TS compiles out enums and hardcodes the enum values during compilation
Something like this should be possible:
But no matter how I bash at the types I am unable to get the type checker to reconcile the relationship between the elements of the enum and the enum in total.