TypeScript Enums are TERRIBLE. Here's Why.

Ғылым және технология

TypeScript enums have worn their welcome. In the early days before string unions became so powerful, there was no other option. Today, though, they are more trouble than they're worth. This talk explores some of the problems with enums as well as some solutions to those problems. No solution is perfect, but perhaps no perfect solution uses TypeScript's enums, either. :P
00:00 how enums work in general
00:45 the value of enums by default
01:00 the first failure of enums
01:30 attempting to fix this problem with required indices
02:00 what do enums look like at runtime?
02:50 another downside: function arguments
03:43 working around the problem with function arguments
04:31 there are footguns (even with workarounds)
04:47 a better approach than enums: POJOs
06:14 audience question: why not just create a string union?
06:59 audience question: runtime values for a bad function argument?
07:56 audience comment: it's still just JavaScript
08:26 audience question: are there any keys on the enum?
09:22 audience comment: TypeScript runtime artifacts === bad
10:06 audience question: how do you deal with variations?
11:25 the satisfies operator could help
12:29 how to solve a new problem introduced by using objects
Aaron Harper (github.com/goodoldneon) is a software engineer who enjoys gardening, biking, and spending too much time and money on an overkill homelab.
Recorded on November 1st 2022 at Cahoots (cahoots.com) in Ann Arbor, Michigan.|
Discord: / discord
Twitter: / mitypescript
Mastodon: fosstodon.org/@MichiganTypeSc...
Instagram: / michigantypescript
TikTok: / michigantypescript

Пікірлер: 274

  • @MichiganTypeScript
    @MichiganTypeScript9 ай бұрын

    Josh Goldberg (of typescript-eslint) came to Michigan and did a response to this video: "Enums are MISUNDERSTOOD (not terrible)". Check it out: kzread.info/dash/bejne/ioiMsq2bgMbcnJc.html

  • @cyphern
    @cyphern Жыл бұрын

    @3:25 I'm not commenting on whether this was a good design decision, but here's the reason that any number is allowed: An enum who's values are numbers is sometimes used for bit masks. For example, your enum might be defined as {foo = 1; bar = 2; baz = 4}. Or in binary, that's 0001, 0010, and 0100. But then these can be combined to say that something which is both foo and bar is a 3 (0011), something which is both foo and baz is 5 (0101) and something which is all three is 7 (0111). If this is to be supported, numbers outside the explicitly defined ones need to be permitted. Perhaps with the modern advances to TS they could efficiently calculate a union of all the possible combinations, but it was implemented with a simpler solution: allow all numbers.

  • @MichaelMolisani

    @MichaelMolisani

    Жыл бұрын

    Good point. TypeScript uses enums in its own codebase quite extensively, but almost exclusively as bit flags rather than the "numeric enum" most end up using these for.

  • @cody83462

    @cody83462

    Жыл бұрын

    Using enums for bit masks totally defeats the purpose of enums in the first place. When doing arithmetics with enums you actually want numbers. You lose type safety completely when allowing this.

  • @AkioJunichiro

    @AkioJunichiro

    Жыл бұрын

    @@cody83462 I don't know what you are talking about but in other language using enum as a mask is a pretty common thing and you are not loosing the type safety either.

  • @cody83462

    @cody83462

    Жыл бұрын

    @@AkioJunichiro If you bitwise OR two enum values and get a result that is not in the enum, this is either not type safe or you just get an integer. Does not make too much sense. But of course you can do it in some languages. Bad design is also a common thing, so just do it.

  • @natrixnatrix

    @natrixnatrix

    Жыл бұрын

    @@cody83462 The point of an enum is to have an integer like type where the underlying value specifically should not be relied upon. It's the same as why you cannot do arithmetic on a void pointer in c. When you are using an enum you are essentially telling other people that the value is not safe to for example store in a database.

  • @ColinRichardson
    @ColinRichardson Жыл бұрын

    What these guys may have benefitted from was putting the 4 types of enums into typescript online playground so you can see the outputted JS "live". So they can actually see the object that using an enum actually produces. This MAY have helped the guy in the back understand. (The 4 types being, enum with no implicit values, enum with explicit numbers, enum with strings, and the dreaded enum with mixed values+duplicated)

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    that's a fantastic point. TypeScript is changing the way they do enums in 5.0 github.com/microsoft/TypeScript/pull/50528 and when a talk on that happens I'll be sure to ask the speaker to show this. it would really make it easer to see. really great suggestion.

  • @ColinRichardson

    @ColinRichardson

    Жыл бұрын

    @@MichiganTypeScript Thanks for the heads up with the upcoming TS 5.0 I love knowing about future features But unless they jump into my lap, I can never be bothered to research them as a lot of the time they drop the proposals and I get all excited for nothing. Fingers crossed for this enum feature. Just to let you know the URL has the ) added to it above. Simple fix but others may not spot it in the future.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@ColinRichardson thanks! updated the URL!

  • @loucyx
    @loucyx Жыл бұрын

    I agree enums are terrible, but your points seem uninformed: 1. The values sorting issue isn't an issue if you use enums correctly. Namely, it would be best if you didn't use that 1 directly, but instead do comparisons and mapping with the enum itself: // Thing you shouldn't do if (value === 1) // This is how it should look like if (value === AuthMethod.voice) 2. The object in runtime has that shape because: // This gives you 1 AuthMethod.voice // This gives you a "voice." AuthMethod[AuthMethod.voice] And you can configure TS to emit the enum values instead of that object. 3. Enums as arguments take any number to enable bitflags. As you showed, the solution is to use strings. 4. The problem with the union type is if the string changes in the future, you have to go to every place used and fix it, while with the enum, you can do F2 and rename the value. Cheers!

  • @Krmpfpks

    @Krmpfpks

    Жыл бұрын

    1) is an issue if you store values in json or a database.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    great explanation!

  • @trapfethen

    @trapfethen

    Жыл бұрын

    1) is an issue when you serialize and deserialize data. If you never save the enum values to persistent storage then you avoid this pitfall. The moment you go to save this value somewhere, you will no have to either contend with this potential, or run face first into it at some later point.

  • @loucyx

    @loucyx

    Жыл бұрын

    @@trapfethen there are ways of dealing with that shortcoming (TS is not the first language to have enums that work that way). Basically you have models that are kept aligned with your types, so when you change your enums, either the DB is updated with the new values, or a map is created for old values. Either way I'm doing way too much work to "defend" enums when I 100% agree they suck and there are better alternatives like just using a plain object.

  • @trapfethen

    @trapfethen

    Жыл бұрын

    @@loucyx Yeah, those are the work-arounds we typically see; however, new devs (or even just devs that aren't familiar with enums) can often run into this problem without realizing. Like you said, you've already put in more time defending enums because you agree they have significant shortcomings. I won't press you to defend a stance you don't actively take. I appreciate the dialog, and hope you have an excellent day!

  • @tommyinb
    @tommyinb Жыл бұрын

    Because numeric enum accepts runtime initialized values. You should not skip reading the handbook.

  • @AkaiKnight

    @AkaiKnight

    Жыл бұрын

    RTFM

  • @bzboii

    @bzboii

    Жыл бұрын

    But by default enums are numeric which seems like a mistake imo

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    oh snap

  • @mveronie
    @mveronie Жыл бұрын

    So having to use a string enum is just too much ... but manually declaring a new type on an object with `typeof Object[keyof typeof Object]` (and `as const`) is a better option? I'm not really sold on this. I'm also not a fan of enums, but I would prefer a string union in most cases.

  • @tankstechtutorials5721

    @tankstechtutorials5721

    Жыл бұрын

    seemed like a bit much to me as well

  • @TheBswan

    @TheBswan

    Жыл бұрын

    Create a generic valuesof type, ez fix.

  • @ibgib

    @ibgib

    Жыл бұрын

    I just responded to @Piotr Kołodziejski who didn't see the light of the speaker's brilliance, so I just refer you to that comment and sum up that enums as numbers suck for logging (though are great if you're doing bitmask operations) and enums as strings preclude you from passing in the string literal. The speaker's method allows you the flexibility to use either the enum `AuthMethod.voice` or the string "voice". Personally I use just the string unions but then add on the constant when I would like the enum-like syntax for readability.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @idgibDOTspace thanks again for the great comment!

  • @0xyz
    @0xyz Жыл бұрын

    Great video, can the editor please keep the screen on the code editor and stop the switching please

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    That's super great feedback! We'll look into more layouts that keep the code visible, but also we'll try to reduce switching away from the code in the future. thanks!

  • @asimpleguy2730
    @asimpleguy2730 Жыл бұрын

    I still don't get how object are better than enums with specified string values. 1. The object typing syntax is more verbose, and it allows the method to accept a string, a thing i would argue is not good since if i rename the the value inside the enum, the method is not going to work anymore. 2. The argument of "yeah it works but you are using a subset of what the enum is, so that's bad" doesn't make any sense

  • @highwind81

    @highwind81

    Жыл бұрын

    The language and tools should serve me not the other way around. If I have to constantly think about which subset of a feature I should use, then we should just go back to the "JavaScript: the good parts" days. The whole point of TypeScript is to unload that cognitive overhead but enum goes against that idea.

  • @asimpleguy2730

    @asimpleguy2730

    Жыл бұрын

    @@highwind81 I personally disagree. We never left the "javascript the good parts" days IMO. If you think about it, best practices are kind of a subset of how you could use a language/framework/tool. We are constantly selecting between what the best way to implement stuff is, simply for the reason that there are multiples way to implement stuff. Think about how many ways you have to iterate through an array, and in that, Typescript will not help you in any way decide if you want to use map or a for each. That's why i think the argument "i shouldn't use a subset" is nonsense.

  • @ibgib

    @ibgib

    Жыл бұрын

    I'm thinking this would inevitably come down to a per use case analysis, but could you give an example of a good time to rename a value "inside" an enum? I personally prefer the flexibility to use the enum-like syntax as needed and the string literals other times, depending on context (in code) and ultimately to maximize readability. For example if I had a function called `foo` I would like to pass in `AuthMethod.voice` as one of the args, but if I had `fooAuthMethod` I might prefer `fooAuthMethod("voice")`. And I absolutely recoil at thinking of changing an enum value, but there are probably good use cases for this and I am probably over-reacting. Note: I often would actually have a single object parameter so I could use named args and thus oftentimes I use the string literal, e.g. `foo({authMethod: "voice"})`.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    one argument I hear a lot from people is they don't like the runtime artifacts that enums produce. at least objects are well understood and simple.

  • @xTheZapper
    @xTheZapper Жыл бұрын

    The first point about adding a new entry and having the enum recalculate the associated numbers is a strength not a downside. It means you don't have to make stupid rules about only adding on the end, or manually numbering yourself. If this is an issue because you're in the situation where you're comparing the actual numerical enum value then you're using enums wrong.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    sure, but what happens when your backend talks to an out-of-date frontend with completely different mappings? I've seen this happen in production and it ain't pretty

  • @trapfethen

    @trapfethen

    Жыл бұрын

    Serialization and Deserialization have entered the chat.

  • @xTheZapper

    @xTheZapper

    Жыл бұрын

    @@MichiganTypeScript I'd create an adapter class to sit in between the two and do all the dirty translation stuff. That way when you update the old code you just remove the adapter and avoid pollution of your nice new code.

  • @xTheZapper

    @xTheZapper

    Жыл бұрын

    @@trapfethen Deserialization is only an issue if you're not loading back into the original enum. MY_ENUM_VALUE might serialize into a value of 42, but it will deserialize back into the enum just fine. If the values are going to a different application with no access to the original enum then that's poor design and you need to think about producing a spec for the enum for the receiver to implement or serializing into something like json where the value can have a description.

  • @trapfethen

    @trapfethen

    Жыл бұрын

    @@xTheZapper you have fundamentally misunderstood. The foot gun operates in the following way. You have an enum with implicit values {cat, dog}. You have an instance of this enum with the dog value (numerically 1). You persist this value to your storage to later recall (you have now saved the numerical value of 1). You now have to extend said enum to {alligator, cat, dog}. Next time your application reloads the previously saved profile, the enum will be deserialized as cat rather than dog as cat now has the implicit value of 1. There are methods of handling this scenario, but the necessity of being aware of the pitfall and proactively implementing a method to circumvent it is what makes it a foot gun.

  • @gleysonsantos3960
    @gleysonsantos3960 Жыл бұрын

    I wouldnt hate this kind of school

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    haha, same here!

  • @RunForPeace-hk1cu
    @RunForPeace-hk1cu Жыл бұрын

    I thought the whole point of enums is to "enumerate" values to numbers. If you use enums like a hashtable (map) ... use a map/object. Enums aren't meant to be super flexible. It was originally designed to be more efficient / less memory intensive them map/object because it is done at compile time. Since Javascript is a interpretive language, enums is kinda pointless unless you are running performance sensitive code, which javascript almost never do. I don't understand what the presenter was doing really.

  • @lurnt5763

    @lurnt5763

    Жыл бұрын

    The presenter states what enums SHOULD be doing (which is how languages like Java support enums): only allowing a set of PREDEFINED constraints. The only reason they enumerate to numbers is for the space efficiency as you mentioned, but that is NOT the point of an enum. We want these types to only take up one of a finite number of possible, discrete values. In typescript, an enum type is not an actually distinct type -- it is just a regular key/value mapping as the presenter states. As a result the typescript compiler does not actually constrain your types without using string values. Look at his explanation from 2:50 onwards. The complaint is that in languages like java, you DO get this constraint -- enum function arguments only allow the predefined enum values, since Enum is its own Object type.

  • @lurnt5763

    @lurnt5763

    Жыл бұрын

    Ok I watched the rest of the video and now I'm more on your side -- wtf is the presenter talking about? I am absolutely baffled that he suggested using objects as a better alternative. It is WAY more terse and harder to maintain especially since the object is mutable. The better (though not perfect) solution would have been Union types...While I also hate typescript enums this is definitely not the better solution

  • @RunForPeace-hk1cu

    @RunForPeace-hk1cu

    Жыл бұрын

    @@lurnt5763 enumerated was invented in C. They are way more efficient than storing keys and values. ESP back when memory is very much limited. Done at. Compile time, there’s no lookup. I’ve been coding since the 80s … :-) Enums are kinda pointless now with interpretive languages, scripts, etc … how many programs nowadays are that performance sensitive? Most developers are writing JavaScripts front end stuff … not kernel drivers :-)

  • @lurnt5763

    @lurnt5763

    Жыл бұрын

    @@RunForPeace-hk1cu Lol fair I am only two years into the industry and just going from my experience using mostly Java + Typescript at work. I feel that today memory is hardly a concern as you mentioned, at least for high level application dev. In practice I have always used enum for the purposes of having predefined values along with strict type safety for those values. While yes there is memory optimization by enumerating it I have never considered it as a *huge* win. Either way you're probably right about the actual purpose of an enum and perhaps people have overloaded its utility over time.

  • @maxpoulin64
    @maxpoulin64 Жыл бұрын

    One of the reasons for the numbers is you can do things like if(2 in AuthMethod) to validate if an input value is a valid value for the enum. The number thing is not useful for external APIs, but it's useful for data structures that remain local because you can do integer operations. For example, state machines. It's not Rust enums but it's pretty decent for JavaScript and what you'd use enums for in JavaScript. Gotta keep in mind that all the TypeScript is gone once compiled, so it can't prevent you from having bad values at runtime, only basic checks at compile time.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Finally. Finally someone mentioned Rust enums. I really really love Rust enums. At first they blew my mind, then I thought I understood them, then they blew my mind again.. today, all I can say for sure is that they're clearly great.

  • @harleyspeedthrust4013

    @harleyspeedthrust4013

    Жыл бұрын

    @@MichiganTypeScript rust enums are fantastic. i've always been underwhelmed by enums until rust enums came along

  • @dealloc

    @dealloc

    Жыл бұрын

    @@MichiganTypeScript Rust enums are similar to algebraic data types found in other functional languages, which makes it so powerful compared to TypeScript. But one missing feature is the ability to use a enum variants as types, like you can with TypeScript. For example `AuthMethod.sms` is a type in and of itself in TS, so you can constrain some value further. This is not possible in Rust, and not easy for them to implement either in the language, unfortunately.

  • @amh1010

    @amh1010

    Жыл бұрын

    @maxpoulin64 if the `2 in AuthMethod` check was the reason then why doesn't that work for string enums? Like if I have `enum Foo { a = 1 }` then `1 in Foo` is true, but if I have `enum Foo { a = "A" }` then `"A" in Foo` is false. In other words, for numeric enums the runtime object's keys are the enum's keys and values, but for string enums the runtime object's keys are only the enum's keys

  • @maxpoulin64

    @maxpoulin64

    Жыл бұрын

    @@amh1010 it's definitely not intuitive and that's where knowing what the code compiles into is useful to know, unfortunately. I think ultimately what it compiles down to is optimized for performance. Integers and arrays are more efficient than maps, so wherever it can it'll use that. As soon as you manually assign the values of your enums, you end up with a map instead. Ultimately you're probably supposed to use enums as constants and not try to do reverse lookups like that. If you really want a map or an array you should use an array, the enum is just a construct that lets the compiler do things for you. Very double edged sword for sure but it's JS...

  • @nomadshiba
    @nomadshiba Жыл бұрын

    i think the reason i prefer enums is, i use `const enum`, so it compiles places where the enum has been used to numbers directly also use "preserveConstEnums": true, so i can still have the object for the enum si still can iterate through them and etc BUT IF i was using your method i would use Symbols instead of strings better for the equality check, but it has its own downsides as well const A = Symbol('A') const B = Symbol('B') const Test = { A, B } as const type Test = typeof Test[keyof typeof Test] export { Test }

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    great suggestion! const enums are often forgotten about

  • @okayestdev5237
    @okayestdev5237 Жыл бұрын

    I'd recommend to avoid using the integer enums (not initializing them with values). Use the string enum aproach. They're fantastic.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    100%

  • @themikeholm
    @themikeholm Жыл бұрын

    I don't really see how using a POJO with an overridden type is worse than using an enum with strings. It's constrained? I would love some more explanation on this point.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I think people prefer it because it's more "obvious" what the runtime artifact will be

  • @LesterFernandezIO
    @LesterFernandezIO Жыл бұрын

    I think we gotta be careful with how we use enums and this talk is good for bringing awareness to the edge cases. But I do think it still has good use cases. One is code-readability. When you see an enum in code, it’s intent and purpose is very clear. But if you use an object, you would maybe need to leave an additional comment in the code; it’s not as clear. Also, when you only care about something’s state and want to track it with arbitrary values, enums with string values are great.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I appreciate the spirit of what you're getting at. I wish the implementation for enums was different and without some of these pitfalls. in the end, at least string unions can do the job pretty well these days

  • @offroaders123
    @offroaders123 Жыл бұрын

    Great video, thank you! Yeah, enums aren't the best haha. I really like using the `[key: string]: CustomType` for interfaces. You can limit what kinds of types a child interface can define specifically, so you can force it to only allow specific value types for the object's keys (I think that is what the last question was about?). I'm a Minecraft guy, and I have been writing an NBT library that does this, if it is any consolation that may help explain it: interface CompoundTag { [name: string]: Tag; } (Tag is a union type of all NBT tags combined)

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    That's cool, I feel like I don't see that syntax for interfaces very often (more for TypeScript types). Is your library public? I'd love to check it out! p.s. how sad were you that archaeology isn't making it into 1.20?? 。゚( ゚இ‸இ゚)゚。

  • @dara-bk5rh

    @dara-bk5rh

    Жыл бұрын

    Isn’t that the same as Record ?

  • @offroaders123

    @offroaders123

    Жыл бұрын

    @@dara-bk5rh Turns out, yeah! I actually only just read about Record yesterday, and it's a wrapper for assigning an index signature to the type.

  • @harleyspeedthrust4013

    @harleyspeedthrust4013

    Жыл бұрын

    @@dara-bk5rh sure thing, but it's better because generics are butt ugly and using Record means that people now have to go look at the type definition for Record and substitute CustomType in for the type argument. also I remember creating NBT objects in Minecraft mods (for Forge) was a pain in the ass because you had to do it in Java which means you needed to go digging through a gazillion NBT-whatever interface implementations to find the right class to use, then you had to construct an object and add the nested tags which also had to be found and constructed in the same way. I think there were static methods to create these blasted NBT objects but if i remember correctly they still had their obfuscated names at the time so you weren't actually 100% sure what they did until you used them. and then if you managed to figure some of the obfuscated shit out, you couldn't submit a readable name to the MCP because their bot was constantly "locked" or something even if you had an account. every time i think about java i get a headache, that language is the absolute worst even worse than javascript

  • @offroaders123

    @offroaders123

    Жыл бұрын

    Thought I replied to your message already, but looks like it got removed maybe? Sorry about that! My library is called NBTify, and it's on NPM and GitHub under my same username. I'd add a link to it, but that may have been why the old comment was taken down? Yeah, I hope Archeology comes part of the next update too!

  • @mintcar
    @mintcar Жыл бұрын

    Making a union out of an array is useful sometimes, but I don't understand why he does that at the end to create the record type. A `Record` will ensure exaustiveness no matter if AuthMethod is a union or an enum, and the value wont somehow be turned into a string. I think they are confusing eachother in this clip.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    you know... I think you might be right about this

  • @adambickford8720
    @adambickford8720 Жыл бұрын

    Type unions seem to make the most sense to me: dead simple, typesafe, exhaustive (add a value, switch will break) and discoverable (ide will offer autocomplete values just like a formal enum): type Bar = "one" | true | 3 function foo(bar : Bar) : string { switch (bar) { case "one": return "won" case true : return "blue" case 3 : return "bout tree fiddy" } } function baz() { assert("won" == foo("one")) assert("blue" == foo(true)) assert("bout tree fiddy" == foo(3)) } baz() Honestly, i wouldn't even create a 'Bar' type if `foo()` is the only call site, just inline it: function foo(bar : "one" | true | 3) : string {...}

  • @TheNewTimeNetwork

    @TheNewTimeNetwork

    Жыл бұрын

    But how do you iterate over all possible values? Imagine like `Bar.values.map(...);` I think that's not possible, because you have *only* a type, and a type can not be used as a value. What you can do is: const Bar = ["one", true, 3] as const; type Bar = typeof Bar[number]; The second line evaluates to `type Bar = "one" | true | 3`, but you can also use `Bar.map()`, `Bar.forEach()` etc. - Bar is a type and also a const array. From this approach on, if you exchange the const array for a const object, you arrive at the approach presented in the video, which provides you with named constants, `Object.keys(Bar)` and `Object.values(Bar)`: const Bar = { A: "one", B: true, C: 3 } as const; type Bar = typeof Bar[keyof typeof Bar]; //

  • @adambickford8720

    @adambickford8720

    Жыл бұрын

    ​@@TheNewTimeNetwork That's way overthinking it imo. i've never had those exotic needs and the straight simplicity easily outweighs that trivia/edge case.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @TheNewTimeNetwork for whatever it's worth, you can iterate through types with "distributive conditional types" and "mapped types" (both different approaches, but often interchangeable)

  • @TheCsakbalint
    @TheCsakbalint Жыл бұрын

    There is a reason, why we require even from junior developers to know why the JavaScript (and TypeScript) is based on duck-typing. If you know that, you know, why the method accepts any number if the values of your enum are numbers. This is the reason why you should always use string values for enum values, because a set of strings is also a valid type and in that way you can limit the amount of possible values you accept.

  • @TheCsakbalint

    @TheCsakbalint

    Жыл бұрын

    Not knowing something and saying it's bad does seem shallow thinking to me.

  • @Monstermash355

    @Monstermash355

    Жыл бұрын

    Most developers don't know that and use numbers, so yes it's bad in the real world, you might aswell just forbid using it

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    yep, however even the TypeScript team is always looking for ways to close this gap. for example strict function types: www.typescriptlang.org/tsconfig#strictFunctionTypes

  • @harleyspeedthrust4013

    @harleyspeedthrust4013

    Жыл бұрын

    @@MichiganTypeScript why would this even be an option? the point of typescript is to add strong typing so why would it ever be allowed to assign a `(string) => whatever` to something that should be a `(string | number) => whatever`?

  • @TheCsakbalint

    @TheCsakbalint

    Жыл бұрын

    @@harleyspeedthrust4013 For example introducing TypeScript to a JavaScript project gradually.

  • @dealloc
    @dealloc Жыл бұрын

    Enums have two problems; one is that non-const enums generates more runtime code than is necessary-it's not emitting an object. The semantics are also different between usage in TS and non-TS code bases; since const enum with string values does not allow TS users passing raw strings, but requires non-TS users to as they cannot use the enum type; but will produce incorrect documentation. Unions solves all of this, because they are interoperable and consistent and provides the same type safety as enums. If you want to use numbers as values and provide more context, just export traditional constants. If you want to constrain them, you can always export a union of those types.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    fantastic comment! I know a lot of people that do exactly what you're suggesting: use string unions

  • @benjamin_fdw
    @benjamin_fdw Жыл бұрын

    This was very interesting, I had to do this infamous trick with the typeof thing especially with templates because I was on a sort of data oriented architecture (you know how crazy one can go on a side project) and it is not easy to figure out but it works pretty well.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I'd love to see more on this: do you have an example?

  • @benjamin_fdw

    @benjamin_fdw

    Жыл бұрын

    @@MichiganTypeScript I think I was talking about something like this: ``` export const AbilityNames = [ 'strength', 'dexterity', 'constitution', 'intelligence', 'wisdom', 'charisma', ] as const; type AbilityTuple = typeof AbilityNames; // this will contain the Abilities as a string union export type Ability = AbilityTuple[number]; // this type can be templated export type Abilities = { [key in Ability]: number; }; /** * Abilities is equivalent to Record */ ```

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@benjamin_fdw very interesting! thanks for explaining!

  • @ibgib
    @ibgib Жыл бұрын

    Loved the video! I am most excited about the code you show at the very end with the new `satisfies` keyword. If I could just force myself to learn it I might break out of my habit formed in the early days of TS before there were enums and before the `keyof` operator...My VsCodeVim habit (I'm not that hardcore!) enables me to lazily parse the union type and construct the constant, where I use the `as AuthMethod` technique. Duplicated code, I know - but very readable for my old eyes!

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I have about 30 things I do that are just "but I've been doing them that way for a long time" coding habits, don't worry, you're in densely populated company

  • @dealloc

    @dealloc

    Жыл бұрын

    But `as` type assertion is a footgun, because it changes the type underneath you and you lose the type safety that satisfies provides. The alternative to satisfies, if you use older TypeScript version, would be to use an identity function with a generic as a constraint: `const foo = (value: T) => value;` where Foo would be your type. Then wrap any value within it like `const someFoo = foo({ a: 1, b: 2 })`. and `typeof someFoo` will now be a narrowed type of Foo, that satisfies its constraints. You also get the type safety within the declaration, since it conforms to Foo. Of course this adds a neglible overhead in terms of runtime, but rather cumbersome boilerplate, which is why the `satisifies` keyword was introduced. It removes the need to wrap every single thing in a custom function just to get a proper narrowed type.

  • @asedtf
    @asedtf Жыл бұрын

    Forcing updates when you add one more thing is potentially bad. Lots of code is "If a, then do x. If b, then do y. Otherwise just do z"

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    totally, that's where I think people get into trouble

  • @jeramymorrill2729
    @jeramymorrill2729 Жыл бұрын

    This feels like willful ignorance of how we actually use / check against enums. yourEnum.VALUE always matches yourEnum.VALUE no matter where you pass it, and thats the point. I will say they can be annoying in reducers if used as an action.type, unfortunately TS complains way less with plain strings...

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    you know, that's a good point. enums would have been perfect for redux actions.. but sadly redux's implementation long predates being able to use TypeScript in React

  • @salka_
    @salka_ Жыл бұрын

    I'd much rather have a lint rule requiring only string enums instead of having to do `as const` and the typeof stuff. And you can make a function accept string literal versions of enum values by having the param typed as `${AuthMethod}`

  • @MichiganTypeScript

    @MichiganTypeScript

    8 ай бұрын

    there's an ESLint rule for that isn't there? prefer-literal-enum-members or something?

  • @ivanjermakov
    @ivanjermakov Жыл бұрын

    I totally agree that enums in TypeScript are a total mess. For personal projects, I always use literal types, e.g. type AuthMethod = 'push' | 'voice' | 'sms'

  • @dealloc

    @dealloc

    Жыл бұрын

    That is the way.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    same

  • @SadieandCompany
    @SadieandCompany Жыл бұрын

    If you teaching people (and its serious), stop saying the reason is because "enums are terrible". Im 3 min in and that was used at least 4 times...

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I think it was meant more lightheartedly, but on a more serious note: do you disagree that they're terrible?

  • @The14Some1
    @The14Some16 ай бұрын

    there is a thing as const enums. Why didn't you cover it here?

  • @MichiganTypeScript

    @MichiganTypeScript

    6 ай бұрын

    check out the follow-up to this talk by Josh Goldberg. if memory serves: he covers it there

  • @adamhenriksson6007
    @adamhenriksson6007 Жыл бұрын

    Bro have you seen python enums? They really make me cry everytime i even consider using them.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I haven't, but I cry anyway when I see python. rip: me

  • @adamhenriksson6007

    @adamhenriksson6007

    Жыл бұрын

    @@MichiganTypeScript Prepare... from enum import Enum class Day(Enum): MONDAY = 1 TUESDAY = 2 WEDNESDAY = 3 # print the enum member print(Day.MONDAY) # Day.MONDAY # get the name of the enum member print(Day.MONDAY.name) # "MONDAY" # get the value of the enum member print(Day.MONDAY.value) # 1 You can iterate through enums, you can compare contents like a set or list, get the length of enums, match against enum keys, and even call the enum class itself like a function to get the enum value. It's like a combination of every single data structure and a hilarious punchline to a programming joke that everyone forgot.

  • @adamhenriksson6007

    @adamhenriksson6007

    Жыл бұрын

    Sadly, the only thing you cannot do is add or remove enum members dynamically. Don't worry though, there is a library for that.... 🤦

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@adamhenriksson6007 wow you weren't kidding

  • @Kubatko
    @Kubatko Жыл бұрын

    Not sure, from the video I see that enums are perfectly safe to use and work exactly as I would expect. As long as you understand them which should be the case for any part of language you use. Any of the alternatives I saw after the initial intro seem to be worse cases and are exactly the reasons why I would use enums.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    that's fair. if it works for you and it makes sense to you then go for it. I've noticed it becomes more of a problem when working with teams (but of course that depends on the makeup of the team)

  • @teC5
    @teC5 Жыл бұрын

    i disagree - enums are great and this is not much different to how they work in C for example. The fact that they get compiled to numbers make it easy to use enums as masks and easy for serialization. It sounds like the only thing you want is a range check on methods accepting the enum, other than that your example defeats many of the purposes of an enum and is gross to setup.

  • @Dorumin

    @Dorumin

    Жыл бұрын

    Enums are misused for bit masks :) they're invalid values, integers should be used for that. And you can simply define them as constants

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I think enums are great as a computer science construct, but it's the "how they're implemented in TypeScript" part where things start to get sticky

  • @teC5

    @teC5

    Жыл бұрын

    @@MichiganTypeScript ah yes, that sounds reasonable. Other then the verbosity of the proposed solution I thought the end result in usage was pretty nice, great talk!

  • @ChillAutos
    @ChillAutos Жыл бұрын

    I can't believe all the fuss over enums. I was expecting this to go way deeper. Why is this more confusing syntax better than string enums and setting up an eslint rule once?

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    You raise a very good point about eslint being able to really help massage things

  • @da-ker
    @da-ker Жыл бұрын

    This is a good example of someone who seems to only do JS/TS development and has no real experience with programming, structures and history of it. Because otherwise he would truly have a different look at enums in TS and in general. Enums aren't bad, the usage is in this example is.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    the typescript team themselves don't seem to agree with you. check out the release notes for 5.0: it contains some attempts to improve some of the things mentioned in this talk

  • @-__-1025
    @-__-1025 Жыл бұрын

    @13:21 you could ... const AuthMethodTitiles: {[k in AuthMethod]: k} = { ... }

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    good call

  • @user-gp2vk8xn8t
    @user-gp2vk8xn8t5 ай бұрын

    just use string enums and don't forget to add Eslint plugin for allowing strings only

  • @MichiganTypeScript

    @MichiganTypeScript

    5 ай бұрын

    why not just use string unions at that point? readability or refactorability or something?

  • @user-gp2vk8xn8t

    @user-gp2vk8xn8t

    5 ай бұрын

    @@MichiganTypeScript You mean like type RPS = 'rock' | 'paper' | 'scissors' ; and then you change `paper` to `lizard` for some reason. doesn't seem like IDE would easily replace all occurances of `paper` with `lizard`. => refactoring reason. And how do I iterate over string unions? much easier is to do Object.values(MyEnum) => usability reason How do i distinguish two different type unions when they have commonly named children? for ex: `emergency` as a filter in list of calls AND `emergency` as an option for new call. => readability reason idk, maybe it's just my limited experience. haven't watched enough of projects :D

  • @MichiganTypeScript

    @MichiganTypeScript

    5 ай бұрын

    @@user-gp2vk8xn8t it turns out, though, that the IDE really can replace all occurrences. give it a try! (F2+rename) if you're iterating over these things as values, why not use an array where the order is stable?

  • @thepetesmith
    @thepetesmith Жыл бұрын

    Try the Record utility type.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I used to dislike the Record helper type but now I think it's really helpful for some situations.

  • @anon_y_mousse
    @anon_y_mousse Жыл бұрын

    I doubt anyone will see this now, but this illustrates why enums should be treated differently. Consider a language like C where there's really no language enforcement to require enums to be a certain way, but most compilers, at least good ones, will have warnings or errors or both that you can enable pertaining to checking them at compile time. If you know what you're doing, you don't even need a warning, let alone an error, but for those that are learning, you can enable it. However, therein lies a problem, as others have stated, they are often used as bit flags and that defies the closed set nature that quite a few want to use them as. I think the best thing a language could do with regard to handling enums and typing them is to have a type constrained addendum to the description for an enumerated type. For instance, if they're going to be used for bit flags, have something like enum as the type and for actually constrained value types use something like enum. Obviously, I don't use TypeScript in my job, and don't even really know it beyond what correlates with JavaScript. Mostly I've been watching these videos to determine if I want to take my knowledge a step further and what I've seen has told me that I wouldn't want to use it to write anything serious. I see a lot of problems with modern day web languages, and quite frankly I'd like to start from scratch in that regard. A lot of what Java did shouldn't have been done and certainly shouldn't have been copied yet nearly every web language since has copied these things. I see a lot of this with regards to markup languages like HTML as well. We really need to wipe the slate clean and start from scratch, but it won't happen and we all know why. It's just too much work, too much that would need to be transitioned and too much already working code exists that to rewrite it would be an enormous undertaking that no one would want to spend money on.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    _I see you, I see you_. for what it's worth, I found this to be a really valuable bit of insight. it's a great point you make.. the one about copying thigns from language to language where it doesn't make sense. Hopefully the content on this channel won't scare you away, but I will say that it's a bit unusual in the sense that it's got a lot more advanced topics and not as many lower and beginner topics. I'd recommend to you and anyone else to take a look at Matt Pocock's work (Total TypeScript) if you're wanting to know more (but, like, in a more controlled and curated fashion). Everything Matt does is great.

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    @@MichiganTypeScript I suppose I'd need to see how it would work with a real project. If you had a favorite open source project that predominately used TypeScript as the language of implementation, that would probably give me a better feel of it as a language.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@anon_y_mousse sure: mui (previously known as material-ui) is a pretty clean codebase. that could be a nice place to look

  • @anon_y_mousse

    @anon_y_mousse

    Жыл бұрын

    @@MichiganTypeScript Thanks, I'll check it out.

  • @charlesoconor
    @charlesoconor Жыл бұрын

    Is no one going to mention why the enum with int values has both! It’s so you can check if a value is part of the enum. You want the ability to check if the int is there as well as the key and since they are guaranteed to never have overlap you. Double backed enums. Sadly you can’t guarantee that in a string enum that some crazy person would map key foo to value bar and then a key bar to foo. So you lose the ability to go from keys to values. Would be cool if it was a compile option. It’s why I prefer int enums

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    on this part: > You want the ability to check if the int is there as well as the key and since they are guaranteed to never have overlap you. I've heard lots of people say this and while I certainly believe you... can you give a real example? I have never wanted this (as far as I understand it) and I've never seen a situation where someone else has wanted it either... and you're not the 20th person I've asked.. I realize "make me an example to educate me" might not be something you have time for, but just thought I'd throw it out there in case you know of a good open-source example where double backed enums are critical.

  • @Verrisin
    @Verrisin Жыл бұрын

    I always thought TS just uses a Union of strings.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    It's definitely highly standard to just use a string union, but sadly some codebases are really stuck on enums despite the problems their implementation in TypeScript causes.

  • @seanroach1915
    @seanroach1915 Жыл бұрын

    This talk immediately seems like it's from the perspective of someone who didn't read the handbook or reference. In reality, anyone familiar with the language would expect this behavior, and that assumption is reductive of any programming language.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    sure, but you gotta admit it's a little hard when the manual changes (sometimes dramatically) ever 4-5 months (note: TypeScript doesn't follow semver). I read "the manual" on VB6 and it hasn't changed since September 1998.

  • @atxorsatti
    @atxorsatti Жыл бұрын

    I disagree to most of the things you said since TS is meant to be more readble js and more debuggable js, so it's ok to have enums behave like this. Execpt the object.values problem. This is shitty af.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Yeah, it's a bummer for sure

  • @jamielambrecht9419
    @jamielambrecht9419 Жыл бұрын

    I love enums. I think the best implementation of enums is in C++. I get particularly annoyed with how Python requires setting a value. I think it is best to only use integers and it should not ever matter what the value is (So it should not be used for things like user data that will change often!). Also using a string is exactly what we are trying to get away from by using enums! Enums are great for things like states, things that have semantic meaning that we want to group in an unordered list, but we only care about the symbolic! It is for the programmer so that we have a nmemonic for some kind of option or state. Before enums, you either had to declare constants for each thing, or use a list of DEFINEs that are evaluated at compile time. That's why I say it shouldn't be used for data that changes where you are going to download the integer value or whatever from a database across changes to the enum values. It should be used for non-persistent internal data where it doesn't matter if the values are consistent from one compile of the software to the next. Data objects for user data in a web-app would not fit this description imho, as they are expected to persist and be carried across updates to the API and database schema. I don't think that enums should be used for data that requires migration or translation as an object format changes. They should be used for lower level run-time states and settings so that the programmer doesn't have to care whether it is the third or seventh or whatever item on the list. In the case of the example for this video, I quite frankly don't understand why you would be making an enum for methods. Methods already act like enums when you're writing code. You can call . without giving an index to the object. That is essentially already acting like an enum, so why would you need "another one" in this case?

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I agree with a lot of this. I don't know for sure, but wonder if we were to go back in time and never have enums in TypeScript... I would.. haha

  • @jamielambrecht9419

    @jamielambrecht9419

    Жыл бұрын

    @@MichiganTypeScript I can appreciate that and I hope I didn't come off any kind of negative way. I still consider myself a "junior" developer, but as an associate working on compilers for a mainframe OS, I have gained a bit of perspective. I by no means consider myself authoritative. But you should see some of the DEFINEs we have in ALGOL, etc. oh boy. ("Extended ALGOL60" has DEFINEs that can simply say SOMETHING(X) = and it is all evaluated by name. Also, the default way of handing parameters in procedure calls are "by-name" rather than by-value or by-reference, meaning that the parameters are evaluated by their symbolic rather than a memory address or literal value. The difference from call-by-reference is subtle, but it basically means if you pass an expression as a "formal parameter", that expression itself will be re-evaluated everytime the "actual parameter" is referenced) Not to mention the GOTOs. I think I fell in love with enums when I tried following along with a C++ RPG game engine project using SFML on youtube, and they were very useful for defining states like IDLE, or WALKING_LEFT, etc. Very nice to have those as identifiers that an IDE can recognize, rather than (worst case) using a string literal value and checking "if state == "WALK_LEFT"", which is something I perhaps unfairly associate with Python, because I happened to see it in some Python code and it bothered me (lol). The nice thing about having a list of states as an enum like that is that you can add more of them, change the order, etc. and you don't have to worry about it. As I said, my perspective on this only applies to things that don't need to be transferred as persistent data across compiles, or communicated between potentially disparate software versions where the literal value may have changed. Also, would like to say I'm sure there is some use case for enumerating methods, I just thought that the simple use case of enums is for a situation where you want values that act like methods of an object, but aren't methods, and you would like them to be defined in a way that is recognized and accounted for by your IDE/compiler. :)

  • @philipbotha6718

    @philipbotha6718

    Жыл бұрын

    @@jamielambrecht9419 Scoped enums in C++ are one of my favourite features. The order of the enums are only important if you're serialising the enum or using the underlying value directly. But then it is better to explicitly assign the value to the enum in its definition.

  • @Wielorybkek
    @Wielorybkek Жыл бұрын

    I don't really see any difference between those approaches. Either way you have to agree with other people to either use objects or string unions or string valued enums etc. People will use enums anyway so... :p

  • @ibgib

    @ibgib

    Жыл бұрын

    Before enums officially came out in TS, I was using the speaker's method - but manually duplicating the `const AuthMethod` using entries like `voice: "voice" as AuthMethod`...basically the ooold way. And when enums came out, I thought the same thing as you (I was pretty excited even that I would be able to simplify the code!). But there are several huge practical differences: 1) If you use the numbers approach, then you lose readability when logging. This is fine if you're looking for blazingly fast code in a tight loop, but really at that point, you might ask why are you using JS/TS? 2) The strings approach that the speaker turns to around 3:45 have a HUGE problem (IMO) in that you lose the ability to choose either `AuthMethod.voice` or "voice". If you pass in just the value string literal, the compiler will complain at you saying "Argument of type '"a"' is not assignable to parameter of type 'AuthMethod'.(2345)" This for me is a non-starter, because sometimes I want to use the enum and sometimes I want to pass in the string directly with compile-time type safety. I'm interested in what he's doing at the veery end of the video using the new `satisfies` keyword, but I'll probably be too lazy and continue to do it the old fashioned way. (I don't even use the `keyof` shorthand he uses at 5:20 - partly because it looks cryptic but mostly because I am just old!)

  • @yikan1107

    @yikan1107

    Жыл бұрын

    Nobody uses enums. In practice it is easier to create a file and just export const. If you need to group tuple like or cardinal information , the object is more flexible and combinable with redux functions.

  • @marcosrolando7987

    @marcosrolando7987

    Жыл бұрын

    @@ibgib Why would you want to pass the string literal? That just seems like a really bad practice because any refactoring to the enum would require manually changing every use of the string literal instead of just modifying the enum value itself, and even ignoring that why would you "sometimes" need to use it as a string? Enums are abstractions and you should use them as such, refering the actual value in the rest of the codebase is (usually) a bad idea, and only really makes sense when translating external input to the enum.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I think there's a lint rule to completely disallow enums

  • @rons96
    @rons96 Жыл бұрын

    Everyone speak bad things about every lang, most to be promoted somehow, but devs never join to improve some lang to be recommended to all situations together just with simple changing in settings. Thousands of langs created along time to replace older langs and the reason is most of devs want to be rich with they created new langs everyday. For example: deno was waste time, why not improve node? And Rust, why not release improved C? The many options just make fix projects hard and confusing to new devs choose the "best" to start studying

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    These are great questions you pose as examples. Deno is effectively _is_ improving node. You might think of it as node 2.0, conceptually speaking. And for Rust, I wondered the same thing before I tried it but there'd simply be no way to "incrementally improve C until you end up at Rust". It's just a different thing with a different set of goals (although, of course, those two sets can sometimes overlap). Still, your overall point is a great one.

  • @Gruby7C1h
    @Gruby7C1h5 ай бұрын

    "Am I a joke to you?" - Bit Masking.

  • @MichiganTypeScript

    @MichiganTypeScript

    5 ай бұрын

    right?? haha. the bit masking element of all of this really is a part that people miscalculate the historical relevance of.

  • @ACHTech20
    @ACHTech20 Жыл бұрын

    6:11 first bench 2nd guy, he is like do I need to clap.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    lol

  • @NootNooot
    @NootNooot Жыл бұрын

    I really wonder how you can love such language.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I ask myself this every day, yet here we are

  • @LarsRyeJeppesen
    @LarsRyeJeppesen Жыл бұрын

    Thanks

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Come again!

  • @xBiggs
    @xBiggs Жыл бұрын

    A lot of these problems are not specific to typescript. Enums often don't give the functionality of a closed set of numbers like people truly want.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    can you give some other examples of languages you have in mind? I don't follow exactly and I'm curious

  • @xBiggs

    @xBiggs

    Жыл бұрын

    @@MichiganTypeScript C and C++ enums decay down to Integer types. If I have a function that accepts an enum parameter, you can supply an argument literal that isn't in the enums range. The same applies if you have an enum variable, you can assign a value outside the enums specified range. Enums arent a closed set of numbers in most languages

  • @jeremiasnater4288
    @jeremiasnater4288 Жыл бұрын

    i would use string enums over number enums and i agree with some of the points. But some of tge reasoning here is really bad, and as you are doing a talk about this you should know that the keys and values are in the enum object so that it can be looked up in both ways.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    right, that much is clear, but _why_ would you need to look them up both ways? care to share a codepen demonstrating this? asking for a friend.

  • @danteDeveloper
    @danteDeveloper Жыл бұрын

    super nice tips about enums!

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Glad you liked it!

  • @jez9999
    @jez9999 Жыл бұрын

    This could just be replaced with "TypeScript is terrible". It's a band-aid on an overly-flexible underlying language and shouldn't be used for anything remotely complex or mission-critical. Use C#.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Why stop there when VB.Net is just as capable?

  • @user-cd6vy2jg6f
    @user-cd6vy2jg6f Жыл бұрын

    2:35 “I have no idea why there’s probably a reason for it” You really shouldn’t give a presentation statement / opinion on something you don’t understand. First rule is know the thing you’re speaking on

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I hear what you're saying, but just to say it out loud at Michigan TypeScript we really encourage a talk like this where the presenter may not know every nuisance. there's a part of the events that unfortunately you can't see on the videos: which is that we all go out to get tacos or drinks or whatever afterwards and often talk about exactly this kind of thing. thanks for watching

  • @blargo
    @blargo Жыл бұрын

    2:35 "I have no idea why; there's probably a reason [enums are implemented this way]". It's so you have a way at runtime to look up the named enum value from the numeric value, and vice versa. Presenter should have taken the time to investigate this, also covered 'const enum', before declaring enums to be TERRIBLE.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    would you be at all swayed by the fact that the runtime artifact is so non-obvious to so many people is itself enough to rank it lowly?

  • @blargo

    @blargo

    Жыл бұрын

    @@MichiganTypeScript Not really. If you treat enum as a type, instead of an object, who cares how it's implemented? If the runtime implementation of enum bothers you, and you don't see the benefit of two-way mapping, just use `const enum`. Sure, the example of not being able to use `Object.values` is a bit surprising at first glance. However, in any real scenario, where you want a human-readable list of the enum values (or more likely, localized versions of the same), you're going to need to perform additional processing/mapping anyway, so it's kind of a non-issue.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@blargo I hear yah. As a library author, I care quite a bit whether the code I'm shipping to my users will be confusing to them or cause them problems (whether justified or not by the "facts of the situation" as to whether they are justified in being confused). There's definitely a very valid "RTFM" rebuttal to many of the criticisms of TypeScript's implementation of Enums.

  • @paherbst524
    @paherbst524 Жыл бұрын

    Ada handles enums the best

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I would genuinely love to hear more about that!

  • @loucadufault6549
    @loucadufault6549 Жыл бұрын

    If I watch a 15 minute video about TS enums, I kinda expect not to be greeted with two "I have no idea why" within the first 3 minutes of the video, that can easily be found by a little research... I am very skeptical to spend my time listening to a presentation where the presenter isn't aware of basic TS concepts like duck typing, and put two and two together to realize that because the enum members resolve to numbers (at least in this setup), and typescript cannot narrow numbers, then of course the method accepts any number due to duck-typing.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Sounds like you've got a talk of your own brewing here. Feel free to reach out!

  • @loucadufault6549

    @loucadufault6549

    Жыл бұрын

    For what it's worth the rest of the presentation was very informative and it's clear from the questions the presenter is quite knowledgeable, I guess just an odd decision to start the presentation that way... Definitely learned a thing or two from the answers during the questions round.

  • @loucadufault6549

    @loucadufault6549

    Жыл бұрын

    @@MichiganTypeScript haha I've amended my comment as I feel it was a little harsh. And I definitely don't have much to share as I still feel I have even more to learn.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@loucadufault6549 that's very kind of you to say! thanks for stopping by!

  • @SongZoneChanel
    @SongZoneChanel Жыл бұрын

    thank 4 share

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    thanks for stopping by!

  • @2Fast4Mellow
    @2Fast4Mellow Жыл бұрын

    If you work with large codebases, stop using enums where interfaces makes more sense. Enum = enumeration. Javascript is not object oriented, but it does emulate it. But what it creates a associative array where members can be a function or a value. In order to support both the enum name and it's value, TS needs to create an array that contains both. That is why object.values gives you both. However if you use an interface, you have to pass an actually instance that conforms to the interface to 'DoSomething' In order to know where you need to alter the code if you introduce a new auth method, you can simply find all places where the interface is used as an argument. Using reflection you can find all implementations of that interface and put it in an assoc array which can be used to show the auth methods names. In pretty much every language enums are evil! Enums are just a construct to remove magic numbers and makes reading the code easier... Am programming for 35+ years and enums still create the same mess as in the 80s...

  • @dealloc

    @dealloc

    Жыл бұрын

    Interfaces and enums are completely different concepts. Use unions. Enums generates more code than necessary, and const enums does not allow passing raw string values, which means that JS code and TS code have different semantics and so are not interoperable.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    The only language I've seen an enum implementation and that I loved was rust

  • @Stubbelur
    @Stubbelur Жыл бұрын

    For those confused, like me, about wth was going on at 12:00, here is ChatGPT's explanation: This code defines a type called AuthMethod that corresponds to the string values in the authMethods array. The as const assertion is used to ensure that the authMethods array is treated as a tuple type rather than a string array. Next, the code defines an object called AuthMethod that has properties with the keys of each value in the authMethods array, and string values for each property. For example, the push property has the value "Push". Finally, the code uses an index type k in AuthMethod to iterate over each value in the authMethods array and create an object property with the key equal to the current value, and the value equal to the corresponding string value in the AuthMethod object. For example, the push property of the object is created with a key of "push" and a value of "Push".

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    wow. this is amazing. I'm gonna have to check this out!

  • @mikaputa2194
    @mikaputa2194 Жыл бұрын

    Great chanel, thx

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Glad you enjoy it!

  • @kbsanders
    @kbsanders Жыл бұрын

    Frustrating when camera person/editor person cuts away from the IDE.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    thanks for this feedback, truly. we'll try to do better in this realm in the future. after all, the code is the most important part of the presentation!

  • @gillall4828
    @gillall4828 Жыл бұрын

    Why not? type AuthMethod = "Push" | "SMS" | "Voice"

  • @LarsRyeJeppesen

    @LarsRyeJeppesen

    Жыл бұрын

    Much harder to change values later, no iterator

  • @Loserfr

    @Loserfr

    Жыл бұрын

    Typing doesn't give you the same thing as an enum. As you can see in the video, you get values from the enum whereas you don't get values from a type.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    A lot of people go for that, yep. I think the part people don't love is where it makes it a little tricky to search your codebase for each and every usage, whereas LSP tools will show you implementations if you use an enum.

  • @gaddp
    @gaddp Жыл бұрын

    Typescript Enums are TERRIBLE, but vim is the BEST.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    have you heard of emacs? my understanding is that it has vim bindings but I haven't tried it yet because I'm still upgrading my machine from 32bit XP

  • @enfieldli9296
    @enfieldli9296 Жыл бұрын

    Interesting and refreshing, thank you!

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Any time. Let us know if there's anything you'd like to hear about next :)

  • @margosdesarian
    @margosdesarian Жыл бұрын

    You would seriously employ someone who would not put the new enum value at the end?

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    sometimes it can be something as simple as a bad merge conflict resolution that can send things off the rails re: enum number ordering

  • @themikeholm
    @themikeholm Жыл бұрын

    enums are terrible because enums are terrible.... maybe let's explain it with different words? granted the number values are problematic, but i don't really see the problem with string values as you put it. all I see from this video is that you want me to type a whole lot more stuff for something which might be slightly better than the builtin four character construct? i think I'll stick with enums for now than all this typeof keyof typeof malarkey

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    power to the people

  • @GuiltyJit
    @GuiltyJit Жыл бұрын

    I'm throwing away enum as much as possible

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    smart move

  • @aram5642
    @aram5642 Жыл бұрын

    Enums are great... until you need to display a dropdown with all possible values.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Even the, Objects will fail you because they are unordered structures. Great point!

  • @aram5642

    @aram5642

    Жыл бұрын

    @@MichiganTypeScript but with objects, I can turn them into Object.entries and sort to my liking :)

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    @@aram5642 100%

  • @Nemhesis10
    @Nemhesis10 Жыл бұрын

    It's beautiful...

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    ain't it?

  • @nsk8ter524
    @nsk8ter524 Жыл бұрын

    Enums suck because a type of string unions does its job better. `type Whatever = 'foo' | 'bar' | 'baz'`. Then you don't have to port the enum all over the app.

  • @LarsRyeJeppesen

    @LarsRyeJeppesen

    Жыл бұрын

    Lots of issues with that.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    totally. unfortunately unions weren't in the language until 1.4, so we're probably stuck with enums for the foreseeable future

  • @FelixFaerber
    @FelixFaerber Жыл бұрын

    channel 5 sticker :)

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    sorry, I don't have cable. what's on channel 5?

  • @FelixFaerber

    @FelixFaerber

    Жыл бұрын

    @@MichiganTypeScript www.youtube.com/@Channel5KZread

  • @fabionunes2793
    @fabionunes2793 Жыл бұрын

    The part that he was complaining about tje object transpiled, well... It's because an enum is a simple map to enforce a key value. He was complaining about the nain reason of an enum. What a waste of time!

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    because TypeScript doesn't have what other languages refer to as opaque types. the example he shows where a function will accept any number for an argument typed as an enum is a great example of the kind of pitfall you don't want enums to allow. All the same, hopefully your day got better after watching this one. apologies for failing to meet your expectations

  • @sidsarasvati
    @sidsarasvati Жыл бұрын

    Is it some new age junior dev ranting ahead of his experience? Some senior engineer needs to take this guy to a) present arguments better b) have better code sense

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    nope, lots and lots of senior devs feel this way too. of course, opinions do vary

  • @beeman-dev
    @beeman-dev Жыл бұрын

    Sorry but I think it's a real far fetched problem. Use Enums with a String/String pair and move on with your life. 🤷‍♂

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    totally: it's definitely not a problem that everyone has to contend with. for better or for worse, though, some codebases use the number style a lot (one of which is the typescript codebase itself)

  • @paherbst524
    @paherbst524 Жыл бұрын

    Just enums? How about "TS is terrible" ;)

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Amen.

  • @issy_dev
    @issy_dev Жыл бұрын

    Really good talk, thank you for sharing these pitfalls and solutions

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    Our pleasure! let us know if there's anything you'd like to see next

  • @jaypacsky
    @jaypacsky Жыл бұрын

    Enum, interfaces in the TS world are useless

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    the enums part I agree with, but why do you find interfaces to be useless? without interfaces module augmentation gets a lot harder.

  • @leeow3n
    @leeow3n Жыл бұрын

    Hyperbolic much?

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    they sorta deserve it tho..

  • @XTANCE
    @XTANCE Жыл бұрын

    Wow people are chill in that Michigan or wherever you at. Here someone says "terrible" about others code he might get his face wrecked.

  • @Grilinctus

    @Grilinctus

    Жыл бұрын

    Wow, that’s messed up.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    it's cold and chilly here, you got that much right!

  • @TheRavageFang
    @TheRavageFang Жыл бұрын

    12:28 that laugh 😂

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    I had a really tough time not making a separate chapter for it. it's wonderful isn't it?

  • @robbieskonieczny9464
    @robbieskonieczny9464 Жыл бұрын

    I also dislike how you can't abstract enum functions compared to a language like Java.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    same

  • @leeow3n
    @leeow3n Жыл бұрын

    Enums are great, you're just terrible at adapting to their design.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    haha, this is a great one. I'm gonna save this somewhere.

  • @DioArsya
    @DioArsya Жыл бұрын

    I want to be there.... haha

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    You're welcome any time! Ann Arbor, Michigan :)

  • @21mighty86
    @21mighty86 Жыл бұрын

    Good video, if you meant it as a joke

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    50/50

  • @kirsanov2008
    @kirsanov2008 Жыл бұрын

    enums are okay, TERRIBLE is that you don't learn your tools and rush to the stage to show people that enums are TERRIBLE 😲, it's bs

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    genuinely, I'd love to know what you're referencing that wasn't learned about the tools

  • @tak68tak
    @tak68tak Жыл бұрын

    terrible camera work

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    what would you like to improve? serious question

  • @cnordbakk
    @cnordbakk Жыл бұрын

    What a weird talk and a TERRIBLE title 🤨If you can't use types right, maybe just stick to all literals.

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    what would have been a better title? ....asking for a friend..

  • @naadodi_tamilan
    @naadodi_tamilan Жыл бұрын

    First of all if you are going to `doThing` and pass multiple types of arguments into it to do multiple things, then you need to separate them out as doSMSThing, doPushThing and so on... Read Code Smell before you post something like this

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    is that book on Amazon or something? got an affiliate link handy by any chance?

  • @naadodi_tamilan

    @naadodi_tamilan

    Жыл бұрын

    Not an affiliate link

  • @sougataghar1179
    @sougataghar1179 Жыл бұрын

    Typescript is terrible itself

  • @denismijatovic1239

    @denismijatovic1239

    Жыл бұрын

    Naked JavaScript is better?

  • @MichiganTypeScript

    @MichiganTypeScript

    Жыл бұрын

    agreed

Келесі