With that said I am curious why you think one shouldn’t use enums. I know it’s a “factory” IIFE like namespaces at runtime but otherwise I don’t understand why it’s undesirable?
1. Because they have a runtime representation, I cannot do `import type` — and I am importing the entire file (which might have a side effect). While it's still not justified (ideally importing should not do anything) the reality in JavaScript is different.
2. I can swap the enum value with a number or a string and it would still work, even if invalid. See https://www.typescriptlang.org/play?#code/KYOwrgtgBAggxgFwJY... for an example
3. On the other hand, I cannot use strings to create an Enum (https://www.typescriptlang.org/play?#code/KYOwrgtgBAygLgJwJY...) — this is the exact opposite of n. 2
4. Duplicates are possible: https://www.typescriptlang.org/play?#code/KYOwrgtgBAIghgTwPI...
Additionally, const enums DO NOT have an associated type. That is a problem in libraries, since users cannot reuse the type definition around (it back ports to a string or a number)
If they were to be part of the standard, it would be another story.
{
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "TSEnumDeclaration",
"message": "Enum restricted."
},
{
"selector": "ClassDeclaration[abstract=true]",
"message": "Abstract class restricted."
},
{
"selector": "TSParameterProperty",
"message": "Parameter property restricted."
}
]
}
}
(TS decorators are already marked experimental)`Object.values(SomeEnum)` is pretty handy, something you can't do with string union types.
Ah thanks for the suggestions. These reminds me scrounging this article https://dev.to/gcanti/getting-started-with-fp-ts-either-vs-v...
My pet peeve doing this in JS/TS is the fact that writing
``` fold( () => someIdealVal, () => someNonIdealVal )(someAssertion(someValue)); ```
means that those functions passed as the parameters might be instantiated at the execution time rather than on compile time. (This is not proven as the final resulting machine code depends on how good the bundler(webpack)/compiler(tsc)/runtime(v8/rhino) is)
For the sake of performance, I am tempted to write it like this
``` const a = () => someIdealVal const b = () => someNonIdealVal
const someFold = fold(a, b); ```
Writing it like this feels worse for readability. The "story of the function" cannot be told top to bottom, therefore other devs who read this must jump between lines non-sequentially like watching Christopher Nolan's memento.
Rather than pitting readability against performance, I prefer to shelve that fold/pipe/chain pattern for later consideration
2.
I can relate to this. Enums are frustrating especially if you have to write library with it.
I have a pretty good time using this alternative instead. https://medium.com/@martin_hotell/10-typescript-pro-tips-pat... this article point number 4
fold(constant('my static fallback'), f)(x)
What sucks about this, as much as it's my preferred pattern, is that without native pattern matching in the language it's unclear which callbacks are for which type constructors. It's not so bad for something like Either, but if you're using something like DatumEither with ~five constructors it's a bit of a mess.
Reading the article, I do have some suggestion:
1. Never use isLeft or isRight; they break the composability of the monad instance — use `fold` instead, as late as possible
2. Do not use Enum in TypeScript — they have a runtime representation in JavaScript that's likely messing up a lot of things. Use string unions to accomplish the same result