function operation(user: User, state: “active” | “inactive”): void
Boom. Done. Enum defined. You want people to use enums? Remove all context switching from the definition process. function operation(user: User, state: “active” | “inactive”): void
Boom. Done. Enum defined. You want people to use enums? Remove all context switching from the definition process.Otherwise, it becomes an absolute mess of “almost” defined correctly.
This comparison appears to be unintentional because the types '"a"' and '"b"' have no overlap.(2367)
https://www.typescriptlang.org/play/?#code/MYewdgzgLgBAZiEAu...It's features like these that make Python/Ruby/etc. type-checkers insufficient substitutes for TypeScript.
I think my example wasn't the best. Of course "active" | "inactive" would get reused. But if it's just a little function flag it could easily be a one-off.
That said, I hate that typescript has many ways of doing it. That's the biggest problem.
There's:
enum SomeEnum {
First,
Second,
}
const enum SomeConstEnum {
A = 1,
B = A * 2,
}
type SomeEnumType = "first" | "second";
const SomeObjectThatIsAnEnum = {
"first": 1
"second": 2
} as const
I always lean towards the `enum` keyword, because I am of the opinion that if you're optimizing for less generated JS (and enums are actually worth optimizing for in this way) you're probably using the wrong language to begin with (unless you're in the browser and have no choice, etc).The reason is that the compilation from `SomeEnum` to JS involves conversion to an object indexer[0].
Should you, in the future, need to (or accidentally) remove or change an enum option, this will fail with an index out of range exception at runtime that is not obvious to track down.
Put it another way: it leaves behind an artifact in the output JS that can be a source of exceptions.
[0] https://www.typescriptlang.org/play/?ssl=5&ssc=2&pln=1&pc=1#...
How is this different from a const object style enum? Or are you more referring to the sum type enum as the better choice here to avoid this.
Generally, if you remove an enum variant, the compiler should warn you if you've used it anywhere else (though of course it can't figure out a dynamic usage)... But this seems like a problem mostly for dynamic code, where you'd probably write some sort of Enum.parse() or Enum.from() static method anyway?
If I'm understanding your comment correctly, the real problem is that when you store the value, remove one, and try to read it back out into the enum it will fail - but in the code I've written so far trying to construct the the enum object almost always consisted of using a function to validate anyway, these days I use zod but before I'd write stuff like:
function isEnum(obj: unknown): obj is Enum {
return obj && typeof obj === 'string' && Object.values(Enum).includes(obj)
}Like Typescript might (for example) represent enums as integers like 1, 2, 3... at runtime.
What happens if you decide to store a “delivery status” enum in a database? You would just be saving a number into the database, which can be hard to understand.
If it’s a string, then the value stored in the database is clearer and doesn’t depend on you being lucky with the Typescript compiler that the same enum type is compiled to the same integers after new releases.
I only realised this issue now, but it’s what I understood after reading that comment.
There may be a really good use case for the enum type, but I think in most cases, string type unions are clearer, easier, and less prone to errors.
I like Typescript's union of string literals approach because its serialised value is never in question. I know exactly what "NORTH" serialises to.
but in the code I've written so far trying to construct the the enum object almost always consisted of using a function to validate anyway
It's exactly this problem and it's not obvious for someone choosing an enum type that the underlying implementation in JS is an object indexer.The gist is: define your enum values as a const array. Then you can generate a TypeScript type based on whatever values you have in there. And, since it's an actual array, you can easily write guards / asserts.
So you end up with something easy to extend and also has compile-time and run-time checks.
def foo(bar: Literal["active", "inactive"])
Seems like there are at least 4: Mypy, Pytype, Pyright, and Pyre
https://github.com/DetachHead/basedpyright
(assuming you can't/don't use MSFT's pylance)