Enums considered harmful

Фильм және анимация

TypeScript enums are not great. In almost all cases, I use an 'as const' with a sprinkling of type magic to express them.
Become a TypeScript Wizard with Matt's TypeScript Course:
www.totaltypescript.com/
Follow Matt on Twitter
/ mattpocockuk

Пікірлер: 471

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

    Forgot to mention in the video, but union types are great alternative to const enums. Want your code to disappear at runtime? Don't need an object representation? Just use a union of strings: type LogLevel = 'DEBUG' | 'WARNING' | 'ERROR';

  • @sachahjkl

    @sachahjkl

    Жыл бұрын

    const LogLevels = ["DEBUG", "INFO", "WARNING", "ERROR"] as const; type LogLevel = typeof LogLevels[number]

  • @mattpocockuk

    @mattpocockuk

    Жыл бұрын

    @@sachahjkl Yes, also a great case. Although LogLevels.includes is annoying.

  • @wlockuz4467

    @wlockuz4467

    Жыл бұрын

    Was about to point this out haha

  • @littlesandra87

    @littlesandra87

    Жыл бұрын

    Does there exist a way to have ESLint or similar give an error if the code contains enums?

  • @arunsp767

    @arunsp767

    Жыл бұрын

    Oh ya, I use this most of the time. I was wondering do we really need enums? Now I know why I thought that 🙂

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

    Enums have worked great for me. Readability and robustness that they introduce outweigh the potential pitfalls IMO. In fact, I've never even run into problems discussed in the video myself

  • @Slashx92

    @Slashx92

    Жыл бұрын

    I did run into problems like having to filter out keys of an enum if it were a number, but only because I was abusing enums to register categories instead of representing the categories as data

  • @Slashx92

    @Slashx92

    Жыл бұрын

    @@austinmajeski9427 yeah it's both of those things. I did that in a proof of concept for myself tho, I usually don't allow myself to be that "creative" if I'm working for a client lol. And I eventually just converted them to objects, since it was data all along

  • @diego-aquino

    @diego-aquino

    Жыл бұрын

    Me too. Many times I had to change union type values and I would have to replace each occurrence in the entire project, while refaforing enums is extremely easy. I also like that TypeScript prevents you from using the enum values directly, as this would negate all benefits of abstracting their values in the first place over union types.

  • @cytherea165

    @cytherea165

    Жыл бұрын

    I agree. If you stick to assigning strings to the enum keys, you avoid all the issues Matt describes. And I actually like that enums force you to write out Enum.Key instead of allowing the use of plain strings (like in string union type) as this makes for much better code maintenance in the long run (if the value changes in the future, you just need to change it in one place). @Matt Pocock, I love your content, but here I really disagree with you. I was expecting a strong case against enums, but I don't see one.

  • @ThisAintMyGithub

    @ThisAintMyGithub

    Жыл бұрын

    I've also been nothing but happy with Enums. The refactor-ability of Enums make a world of difference

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

    The best thing about the content of this channel is that they're short, succinct but massively useful. Much better than watching a 60 minutes presentation

  • @mattpocockuk

    @mattpocockuk

    Жыл бұрын

    Thanks pal! I thought I rambled a bit in this one by my standards.

  • @driden1987

    @driden1987

    Жыл бұрын

    +1 they are compact filled with knowledge. It’s probably the best format for a KZread video ❤

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

    Hey Matt, I like how you express yourself. Well-paced and with plenty of depth without getting long-winded. Awesome!

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

    I have to disagree. After watching the video i feel like i prefer Enums the way they are in Typescript, than what you proposed. Not that i have not messed it up once or twice before, but i think, as you said, i would really dislike allowing strings in places where i require an enum. It's the reason i use the enums in the first place. In most cases you are also not supposed to dereference enums, i would say.

  • @Scuubie

    @Scuubie

    Жыл бұрын

    Additionally the use case shown from 6:16 does work the same with enums if you assign the strings to the keys. Using enums instead of strings makes it also way easier to rename the keys or values.

  • @snnsnn

    @snnsnn

    Жыл бұрын

    Also using zero based unions of numbers prone to bugs due to being falsy.

  • @iamstickfigure

    @iamstickfigure

    Жыл бұрын

    @@Scuubie Yeah.... I found it pretty annoying that he made it seem like a label map is required at 7:19. Like, he already showed earlier in the video that you can use strings as values for the enums. And doing so eliminates every problem mentioned in the video. The only "problem" it doesn't solve is that it doesn't let you use strings instead of the enum, which I think is actually a good thing. I found the majority of the video to be a really bad take overall. Also, the thing with LogLevel and LogLevel2 at 3:50 is just ridiculous. If you end up in a situation where you have two different enums that represent similar states, it was either a mistake that could be refactored, or there's an important distinction, or each enum is from a different code library. In any case, if you find yourself in this situation and can't refactor your way out of it, "just using the string values" is like the worst choice you could make. Lol. Most likely, the right decision would be to have some function that converts one enum to the other. Even if you're using the "as const" thing, using the string values on their own just seems like a bad idea

  • @Scuubie

    @Scuubie

    Жыл бұрын

    @@iamstickfigure and if you wanna use strings in your code, just use a union type.

  • @n00dle_king

    @n00dle_king

    Жыл бұрын

    Yeah I’d absolutely reject a PR that uses strings and “enums” interchangeably it’s not maintainable and reeks of the sort of thing you’d do in a small single developer codebase because you think you can remember all your cute tricks a year later.

  • @artu-hnrq
    @artu-hnrq10 ай бұрын

    My Typescript understanding has improved a lot since I started to watch your videos, Matt. Thanks for that

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

    commenting to support the channel. loving the content lately, hopefully more to come!

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

    Honestly the fact that enums aren't just structural is an advantage to me. The main point of using enums is that you use enums and not strings. String enums have the best behaviour out of all the options mentioned.

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

    Nice, your approach explaining things is really objective and I love the pacing of the whole video. Thank you!

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

    A lot of the things you call weird are safeguards. Passing some random string as typed enum argument should always be an error. Do you want someone to pass in 'debug' when there will be a comparison against 'DEBUG'? You say breaking the rules, I say following the rules. Literals are almost always a code smell in my book. An ability to exchange enums is asking for trouble. @6:47 you've just rewritten enums that use '=' syntax as a const and made the string formatting more verbose.

  • @kumailn7662

    @kumailn7662

    7 ай бұрын

    right, what you said i have the similar thoughts while listening to the video.

  • @JonathanRose24

    @JonathanRose24

    5 ай бұрын

    But the values of the string literals are still type checked. You can't pass any string literal that isnt allowed. So if you are only allowing 'DEBUG' and you pass 'debug' it will be an error

  • @NuncNuncNuncNunc

    @NuncNuncNuncNunc

    5 ай бұрын

    @@JonathanRose24 Here's a small demo of enum being "stronger" than literal function litfun(flag: LitFlag) { .... } function efun(flag: EnumFlag) {...} if both have "debug" in their type, you can pass EnumFlag's "debug" to litfun, but you can't pass literal "debug" to efun. Example is contrived, but the point is to show that sometime you want an explicit type, not just a string that happens to match.

  • @JonathanRose24

    @JonathanRose24

    5 ай бұрын

    @@NuncNuncNuncNunc ok but how’s this a benefit? To me this is a negative as pointed out in the video because it works differently than how types work for everything else, that being structural typing. I guess where we differ is that I see no value in this explicit type.

  • @NuncNuncNuncNunc

    @NuncNuncNuncNunc

    5 ай бұрын

    ​@@JonathanRose24 Then it is a matter of preference. We're stuck with typescript comparing shape instead of type. My preference is for type checking. With respect typing, some use branded/tagged types to get better type safety. NgRx Actions feel like a proto version of this pattern. It's a pain having to do runtime type checks, but it's the best the language allows. PS I use both literals and enums where I feel appropriate, so this is not a dogmatic position.

  • @RyanTipps
    @RyanTipps9 ай бұрын

    such an underrated channel - thank you so much!

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

    wow we were using enums as constants for some form field naming and it was super annoying to try and pass in values we know were suppose to work at runtime but enums were not happy about that (like just passing in the raw string) thank you matt!

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

    2:25 I don't think this defeats the purpose of enums and in fact should be the recommended way of using enums since it mirrors the const object. I find you don't want to ever allow bare strings as values that as supposed to be mapped to a specific thing...makes refactoring much harder...and I also make it a rule not to look at compiled code and stick to the actual source. I use enums like this: enum LogLevelEnum { debug = 'DEBUG', warning = 'WARNING', error = 'ERROR', } type LogKeys = keyof typeof LogLevelEnum; type LogLevel = typeof LogLevelEnum[LogKeys]; let logLevel: LogLevel = LogLevelEnum.debug;

  • @iamstickfigure

    @iamstickfigure

    Жыл бұрын

    Yeah, the thing he said about it defeating the purpose of an enum was incredibly silly and nonsensical. Especially since his recommended method involves making a POJO with strings as the values anyway. Lol. It's basically the exact same thing, but the only difference is that his method requires a ton of boilerplate, and it allows people to use strings instead of the enum, which, as you also pointed out, is a really terrible idea. Lol. I really do not understand the point of this video other than to warn people not to declare bare enums that auto-define number values. That is a useful thing that I learned from this video. Everything else seemed like it wasn't thought through very well....

  • @envo2199

    @envo2199

    Жыл бұрын

    did you use enums in a proper language like c#? He is right, it is not how an enum should behave.

  • @RegalWK

    @RegalWK

    10 ай бұрын

    you can just type. enum LogLevelEnum { debug = 'DEBUG', warning = 'WARNING', error = 'ERROR', } let logLevel: LogLevelEnum = LogLevelEnum.debug

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

    i like the `keyof typeof` solution the most ❤ it's just so simple and versatile. Nice vod!

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

    If you'd like to allow the string representation of the enum you can do something similar enum LogLevel { DEBUG = 'DEBUG', WARNING = 'WARNING', ERROR = 'ERROR', } function log(message: string, level: LogLevel | `${LogLevel}`) { } log('Hello!', LogLevel.DEBUG); // Works log('Hello!', 'DEBUG'); // Also works

  • @dealloc

    @dealloc

    Жыл бұрын

    Yep. This makes enums even more pointless than they already are. One could argue that invariance is good-in that two different enum types with same value should not be considered the same-although I myself disagree this is a good thing, because "DEBUG" is "DEBUG" is "DEBUG". Always. But in your example the enum is now just overhead (emitted code + leaky abstraction). I could see this as being a good way to introduce temporary types in order to refactor _away_ from enums, so to stay compatible with existing code while also forwards compatible with unions. Good thing!

  • @williamdrum9899

    @williamdrum9899

    Жыл бұрын

    Why weren't enums just a nickname that the compiler replaces with the number at compile time?

  • @dealloc

    @dealloc

    Жыл бұрын

    @@williamdrum9899 You can with const enum, but those are even more terrible for consumers that use JavaScript, because they have the same constraints as enum but aren't accessible by JavaScript.

  • @rcnhsuailsnyfiue2

    @rcnhsuailsnyfiue2

    Жыл бұрын

    This defeats the point of enums. Enums are *not* strings, they represent states. The states they represent can be “backed by” strings, but a string “DEBUG” is NOT the same as an enum with a key called DEBUG.

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

    Here's me again coming to one of your videos with a PR in with the exact thing you tell not to do. Thanks for your content! And definitely important to ask for the like as well. I would never remember to do it otherwise.

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

    without the re-enacting of 'hey maccarena' by the hands: One of the better instructional videos on ts i have seen.

  • @yolamontalvan9502
    @yolamontalvan95029 ай бұрын

    Professor, This what I was looking for. Thanks. I subscribed.

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

    i have different opinions on TS enums: 1- i think (like you said) the enums are the best option for code refactoring, and a great solution for keeping values throughout your code base the same. (when you change the values in one place, they change in every place the enum is used, if you just pass arguments from an enum, but as just strings, you will need to change every place that value is used); 2- about the thing that you shouldn't be explicit when using enums, because it sort of defeats it's purpose, i 100% agree with that, but i also think being explicit is way better than implicit, because someone may change the order of variables (in a conflict from merging, for example) and change it's values, or is just too inexperienced and mess something up; 3- (and this is about everything in transpiled JS) about the way it is done in javascript when transpiled, i think if it performs great, do it's job without problems and will not be a problem for the developers and users in the future, it shouldn't be something you care that much about, because you will not see this code, what you see/code is TS, the JS is just runned by the engine.

  • @gamechannel1271

    @gamechannel1271

    Жыл бұрын

    #2 only matters if you ever do any operation the checks or stores/reads the numeric value of the enum explicitly.

  • @MenelBOT

    @MenelBOT

    8 ай бұрын

    ran*

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

    Gonna make a few dot points to try understand what youre saying - 1. Enums, when compiled, map in both direction. Meaning if you are treating it like an object, you will have extra key: value pairs that you need to expect. 2. Typescript cares about the Names of Enums. You cant use the Values of the enums in place of the name of the enum. 3. A neat alternative can be either Union Types or Const Object 4. Const Object together with ObjectValues type has the benefit of being able to use the Name or value of the item. Benefits of Enums naming without the above two issues. 5. Another Benefit is having the Object have a machine readable key, with a human readable representation of the key as the value. Thanks for the tips! :)

  • @_danyg_

    @_danyg_

    Жыл бұрын

    BE AWARE: 1. Don't treat them as Objects, treat thems as Enums, maybe read how enums works in other languages to grasp the concept, maybe Java or C# or python, if you need to treat them as object, maybe are not enums or you need an extra map to define what you actually need. 2. if my data object has a propery call state, and its value is @ to define that is 'pending' (coming from backend) I can create a enum PENDING='@' and then check for obj.state === MyEnum.PENDING, if backend changes this to a string 'pending', I change the value of the enum and my code continue working. The concept of Pending still there, my code still readable, and the implementation of how pending is is protected by the enum. 3. This create problems when you try to create a list of values in a whitelist, you MUST typed the array that will contain those values, as ObjectValues[], using enums you don't need to because TS can infer it. The same happen every time you need to use that ConstEnum you need to specify that you require the values, at the end you endup exporting a MyContEnumValues then you are using 2 types for 1 enum, values and the map access to those values... is messy 4. Value of the enum shouldn't be used, if you need to use the Value then your abstraction is wrong somewhere, that value is representing somethign that you are not naming or/and your code is not specifing as necessary. 5. This is a given in enums enum States { Pending='%wait%' // Human readable = machine value, which you as developer shound't care how is even called. }

  • @tunoajohnson256

    @tunoajohnson256

    Жыл бұрын

    @@_danyg_ Good stuff, I like the outlook. Thanks for sharing

  • @Johnny-rn8fb
    @Johnny-rn8fb Жыл бұрын

    very rarely such quality content

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

    I wasn't even aware of this pitfalls of the enum, thanks!

  • @antonioquintero-felizzola5334
    @antonioquintero-felizzola5334 Жыл бұрын

    Matt, I've been wondering the same thing over and over again. You just made it very clear. Thanks a lot.

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

    Enums all the way in big scale projects. You don't want to refactor hardcoded strings. Expression like log('Hey', 'DEBUG') is more harmful than log('Hey', LogLevel.DEBUG). (Unless you don't care about the future of your project)

  • @Dxpress_

    @Dxpress_

    Жыл бұрын

    In other languages I'd agree, however in TypeScript, you don't have to use "string" type parameters as an alternative; you can explicitly define a constant set of string values as a unique type, and pass in that type as a function parameter instead. type LogLevel = 'DEBUG' | 'WARNING' | 'ERROR'; function log(message: string, level: LogLevel) { } log('Hello', 'DEBUG'); // OK. log('Hello', 'ABC'); // Immediate compile-time error. This still has all the compile-time & refactoring benefits as enums. In VSCode, you can refactor/rename any value of the type and have it be updated everywhere its used like usual. As you're inputting parameters for functions, Intellisense will suggest only the valid values that can be used like usual. If you input anything that's not one of the valid defined values for the type, you get a compile-time type-matching error like usual.

  • @coolemur976

    @coolemur976

    Жыл бұрын

    @@Dxpress_ Sadly no, it doesn't replace all occurrences when you rename literal type.

  • @Dxpress_

    @Dxpress_

    Жыл бұрын

    ​@@coolemur976 Where does it not replace occurrences? I just tried it now and it seems to work fine.

  • @coolemur976

    @coolemur976

    Жыл бұрын

    @@Dxpress_ I just tried it and it didn't replace some occurrences in React component prop. Moreover, when I search "find all references" by given literal type, it finds strings that doesn't belong to type being searched. Enums are much safer for refactoring.

  • @Dxpress_

    @Dxpress_

    Жыл бұрын

    @@coolemur976 Aye, fair enough then.

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

    Thanks for explaining the IIFE joke to us. That totally made it much better... XD

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

    Thanks, love your content!

  • @mocastello9253
    @mocastello92537 ай бұрын

    great video! thank you!

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

    I am using enums for my whole framework. They are perfectly fine

  • @JamesQQuick
    @JamesQQuick2 ай бұрын

    Great video!

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

    This video doesn't deserve a like - it deserves a love button! Thanks!

  • @yolamontalvan9502
    @yolamontalvan95029 ай бұрын

    I usually use const in upper case to create words used as words in C+. Works for me. In C#, I use enums.

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

    3:13 the point of an enum is *not* to represent a value, but a state. That’s why it’s not as straightforward as just passing the string “DEBUG”, because enums are not strings. Their values can be *backed by* strings, but their values are predefined and not variable. Enums act like their own types, and an arbitrary string can never be the same type as an enum whose value is backed by a string.

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

    Actually you don't need different names for const asserted enums and their type. You can have "const LogLevel = { ... } as const;" and "type LogLevel = ObjectValues;" in the same file. That's basically how @prisma/client generates enums from the schema.

  • @user-cg5jj2yf3y

    @user-cg5jj2yf3y

    Жыл бұрын

    Unfortunately, this is not perfect. The problem arises if you want to use "LogLevel.Debug" as a type, but are already importing both the type and the object. With enums it would be "type DebugMessage = { level: LogLevel.Debug; message: string; }". With as const typescript won't let you, so you'll need to write "type DebugMessage = { level: typeof LogLevel.Debug; message: string; }".

  • @mahmutjomaa6345

    @mahmutjomaa6345

    Жыл бұрын

    @@user-cg5jj2yf3y Good point. You can "import type" and rename the import in such rare case where you import both and need to distinguish between type and const.

  • @Mi2ey
    @Mi2ey9 ай бұрын

    I can see the value in some of the solutions outlined in this video, but the one thing I find most useful about using enums is when working in a larger dev departments. Especially if some of the code may at some point be touched or viewed by members of other teams. It keeps uniformity in how you pass certain values, easy to check the available options with minimal code, and makes it easy to look up where it is used within a project. I like the as const approach, but I can't say that the arguments here against enums at least for most of my use cases justify a change in convention within a stable, well performing and large codebase. Nevertheless, the information is great to know and offers fantastic insights into the inner workings of TS!

  • @OP-tw6bf
    @OP-tw6bf9 ай бұрын

    Is there a tslint warning that you can use to discourage enums?

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

    Amazing video Matt... Thanks...

  • @quantum_dongle
    @quantum_dongle9 ай бұрын

    I think there is a distinction that needs to be made for using explicitly assigned enum values. The default behavior of enums, and the 'as const' behavior is a little odd, but using them as a glorified string map forces users of the code to be explicit about where the values they are using are coming from, rather than passing a string literal into a function.

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

    I use enums alot, and always with the string version. Never had a problem. If you don't assign strings to each enum property, then it defeats the purpose, because then you need to know by heart which index refers to which input

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

    Nicely explained.. I'm looking forward for more on typescript from you..and yeah I want you to have your mustache back as well..😉

  • @StuartLoria
    @StuartLoria3 ай бұрын

    His british-english is american-english friendly, and he makes things clear, which is a first from a skinny smart guy, well done Sir.

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

    Oh wow, that why I had such an initial pain with TS, that explains a lot 😮

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

    Great explanation and nice video! I will still be using them though 😄 Working in a team the solution with "as const" and "typeof keyof" just seems a little too confusing. Plus I do not see the described flaws ever matter in a project where enums are used to define some values that would otherwise be hardcoded somewhere in the project

  • @thiagoalmeida5437
    @thiagoalmeida54379 ай бұрын

    Interesting discussion, some of points that I like about "number" enums: - Ability to do: if (currentLogLevel >= LogLevel.INFO)... - Ability to group things: if(currentLogLevel = LogLevel.WARN)... - Small serialization footprint

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

    IIFE 🤣. Great video again! And completely agree with you that enums add little value (but more size) to your codebase 🎉

  • @code-island
    @code-island Жыл бұрын

    This is Amazing Matt, keep bringing this day to day useful tips in typescript

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

    It's regrettable how awful TS enums are, not only for the quirks covered in this video, but also because of the missed opportunity to be an algebraic data type. Over in Rust land enums are quite powerful, not only in their ability to express variants of many types, but also in the way in which they can be comprehensively matched over and in how serialization/deserialization behavior can be derived and annotated as to also support things like tagged types. Error and Result enums are both incredibly useful

  • @cat-.-

    @cat-.-

    Жыл бұрын

    How would you reconcile an ADT concept with duck typing though? enum Result { Ok(T); Error(E) } // how do you think this should be compiled to JS?

  • @scheimong

    @scheimong

    Жыл бұрын

    Don't blame TS for this, blame JS. It's difficult to build something good on top of an "embarrassing toy language". Rubbish in, Rubbish out.

  • @MrJester831

    @MrJester831

    Жыл бұрын

    @@scheimong there's nothing about JS that prevents TS from having good enums, TS just is weak sauce

  • @PeterAuto1

    @PeterAuto1

    Жыл бұрын

    ​@@cat-.- simply as a Tagged Union Ok(1) = { tag: "Ok", val: 1} Err("failure") = { tag: "Err", val: "failure"}

  • @alguienmasraro915

    @alguienmasraro915

    Жыл бұрын

    Enums are not awful. You just don't know what their use is for.

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

    3rd time in a week revisiting this video. I turned the two type definitions into a one liner. Not sure if there is an issue with it but at first glance it seems to work fine for me. " type LogLevel = typeof SIZE[keyof typeof SIZE];"

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

    @6:22 I came across something like this (forget where) and I have used systems like that and it is very very useful.

  • @YeloPartyHat
    @YeloPartyHat4 ай бұрын

    Going through all your videos. I had no idea about those runtime qwerks!

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

    Awesome video, thank you so much!

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

    About the `as const`, can I somehow get the typescript compiler to understand that the `.find()` method will definitely find an array entry with this? I mean having a const array with maybe objects inside and you want to find an entry of that `as const` array, where you know at compile time, that it will be there. The return type of `.find()` is still `T | undefined`, the `undefined` being for the case where the item won't be found. But I know it will be found, the array is not changed. Is there a way to achieve this and save the if(exists) checks and optional chaining?

  • @arber10
    @arber1010 ай бұрын

    Didn‘t even need to remove the fullscreen to press 👍🏻. Thanks!

  • @josevargas686
    @josevargas6868 ай бұрын

    Enums are good when you want to bail out of duck typing, sometimes duck typing breaks things.

  • @csupakabra4
    @csupakabra48 ай бұрын

    So what exactly is the advantage of obect as const over string enum?

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

    Omg, "as const" really sounds as a killer :O Thank you, Matt!!!!!!!!!!!!

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

    Any opinions on as const vs. Object.freeze'ing the "enum" object? They both function apparently the same to TS (e.g. you can still do the `keyof typeof` and it constrains your strings to a union of the values) except Object.freeze also gives you the runtime safety that as const is emulating in the type language.

  • @igorswies5913

    @igorswies5913

    Жыл бұрын

    why have runtime safety if you can have compile-time safety

  • @JohnLandgrave

    @JohnLandgrave

    Жыл бұрын

    @@igorswies5913 even better, why not have both? If you are the only dev that will ever touch the project, sure. But if the project is sufficiently large and/or successful I don't see why you wouldn't want more safety around something that should be constant throughout the lifecycle of the program?

  • @michaelpumo83
    @michaelpumo839 ай бұрын

    What’s the advantage of a POJO with “as const” over something like a union of strings?

  • @mattpocockuk

    @mattpocockuk

    9 ай бұрын

    Because you have it as a value, so you do things like Object.values etc.

  • @paulsanchez5030
    @paulsanchez503010 ай бұрын

    Great vid. I have to acknowledge. Javascript may be one of those lands that are a bit odd in some implementations., but it is one of the most satisfying languages to learn. I still enjoy how much I can easily do with it.

  • @AruljothySundramoorthy
    @AruljothySundramoorthy9 ай бұрын

    nice explanation

  • @user-kt7li4le8s
    @user-kt7li4le8s10 ай бұрын

    I was thinking on why a certain enum doesn't act well as a type for hours just today... const ... as const is a blessing 😅

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

    Enums made me waste a few days trying to figure out why my tree shaking was not working. It was cause enums. When the bundler goes through, it sees the self invoking function as a side effect and includes it no matter what.

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

    The first example is actually exactly how I expect Enums to work, there is the ordinal value of the Enum and then there is the value you assign for the Enum itself.

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

    What do you think about the upcoming typescript 5.0 enum unification?

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

    I'm glad to watch videos like this and see good points, but ones that I don't 100% agree on. The are many ways to problem solve and it's interesting seeing other ways.

  • @user-ui2ko1ob5y
    @user-ui2ko1ob5y4 ай бұрын

    Thanks for the video! I personally use a lot of typescript enums but I still liked this video. After listening to this, I would also be fine with a code base lacking enums and using e.g. { ... } as const instead.

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

    Where can I watch the interview you mention ate the beginning of the video?

  • @_skeptik
    @_skeptik7 ай бұрын

    Ok, i'm using 'const enum' from now on, thank you : )

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

    I had 1 enum for languages in my new app, just refactored to const as const! 😁

  • @mattpocockuk

    @mattpocockuk

    Жыл бұрын

    Woohoo!

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

    The dad joke at 2:38 made me immediately like and subscribe :)

  • @olduniverse9270
    @olduniverse927011 ай бұрын

    6:34 the little problem with this example, in my opinion, is if you didn't write a log function and just want to use it, you have no idea that you can use LOG_LEVEL object keys as an argument. You see a type LogLevel, maybe you tried to open a quote and realized that you can use some string values. But you should go to LogLevel declaration to see that this type is keys of object, so you can use this object. But I use this approach too.

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

    I don't agree with the general take of this video. If you use enums with string values, such as enum LogLevel { DEBUG: 'Debug', WARN: 'Warn', ... }, you have best of both worlds: strictness and predictability. I think the "as const" approach defeats the purpose, because you shouldn't want to pass the value of the enum, because you shouldn't be interested in the value, but only what it represents, i.e. LogLevel.DEBUG makes sense, but whether its value is 'DEBUG', 'debug', 'Debug', or 'dEbUg', I really shouldn't care.

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

    A trivial point and it may be my editor theme, but I like being able to distinguish between an enum, object and string by their color.

  • @David-oc8yt
    @David-oc8yt3 ай бұрын

    Coming from a C++ background, and given the described potential security issues with const, I much prefer the default implementation (non-const enum)

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

    But theoretically, isn't it still possible to edit individual members of the constant once the code is transpiled into js? For example, in case I insert a line in ts that modifies a member of it, putting a comment in front of it to ignore the possible error, the code would be transposed into js, completely ignoring 'as const' placed in ts. Wouldn't it be a better idea to use Object.freeze({...}) instead of 'as const'? Since this is a POJO, I imagine that it would be better to exploit js to 'freeze' the object even at runtime kzread.info/dash/bejne/nJ6BxLKtj6uZgrQ.html

  • @yasscat5484
    @yasscat54849 ай бұрын

    these "don't use X" videos rarely make sense

  • @rajeshpeddalachugari
    @rajeshpeddalachugari9 ай бұрын

    I just use literal types most of the times like type x = 'a' | 'b' | 'c' . I think its all about personal preferences 😃

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

    Any link to interview with Anders you've mentioned?

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

    Could you please explain why we can't just apply the same mapping to the enum and assign a human frienly value to enum case at 7:11?

  • @yevheniimedvedev3850
    @yevheniimedvedev38508 ай бұрын

    thank you, that's nuts

  • @eXquisiteBuddy
    @eXquisiteBuddy5 ай бұрын

    Swift has a really cool thing where when you press '.' and the definition expects an enum you get the autocomplete.

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

    I think saying "don't use enums" is incorrect. I use them, and all of the "weird" things you mentioned I make use of. But I would agree that you shouldn't use enums if you don't fully understand how they work.

  • @denisonnunes1187
    @denisonnunes11874 ай бұрын

    Do you think about fixing the enum problem in the td-reset library

  • @mattpocockuk

    @mattpocockuk

    4 ай бұрын

    It's not really something we can touch because ts-reset only looks at global typings, not runtime behaviour.

  • @MK-bx8xv
    @MK-bx8xv Жыл бұрын

    3:15 it does work for regular numeric enums.

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

    I find myself using enums quite a lot. The main reason I use them over something like union types is that our codebase isn't 100% in typescript - we are still using Vue 2 and we don't use typescript in the components - so using enums helps me to avoid typos.

  • @dealloc

    @dealloc

    Жыл бұрын

    You don't use an IDE that auto completes? Use it! Unions would also tell you when you made a typo anyway. Use the TS type checker in your JS files (add @ts-check comment at the top of your files), and you will avoid a ton of problems from typos. Typos shouldn't be the factor that introduces bugs in your code. This is one of the reasons to use TypeScript in the first place.

  • @jalub014

    @jalub014

    Жыл бұрын

    @@dealloc Guess that it would need more work than that since when I add the comment all the properties from mixins error out.

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

    Could you argue that something like tsup which automatically inlines enums if possible and bitfields are good arguments for enum usage?

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

    Loving IIFE joke))) Although took your explanation to even catch that.

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

    Enums in TypeScript behave exactly as I expected as a Java, Python, C#, and C++ software engineer.

  • @alice-smith
    @alice-smith Жыл бұрын

    Hay Matt! how would you use a POJO keys as a zod schema enum??

  • @mattpocockuk

    @mattpocockuk

    Жыл бұрын

    z.enum(Object.values(POJO))

  • @alice-smith

    @alice-smith

    Жыл бұрын

    @@mattpocockuk It doesn't seems to work. It expects values to be `readonly [string, ...string[]]`

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

    Can this be used to replace library code for enums?

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

    Ah thankyou needed this

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

    I actually chuckled at the IIFE joke 🤣

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

    This happens mainly because TypeScript drops its symbols into the parent namespace (or object) as well as having it's own, and also it doesn't have a concept of a type scope resolution operator that's different than the instance scope resolution. There also shouldn't be an enum that uses strings. The whole point of enums in C, C++, C#, and D is to create symbols rather than strings. (See SCHEME symbols vs. strings) The enums in Haxe, OCaml, and Rust are MUCH better, and interestingly, they are actually represented with a linear memory layout in Rust due to the availibilty of value types for more than primatives.

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

    Waiting for the next video "Don't use letters! They can be harmful"

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

    Enums can be a real assassin on runtime / build time when it's imported from a 'd.ts' file. In this specific case eslint might not even tell you that the enum 'type' is used as a value. It does really requires some extra attention.

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

    When do you think you will drop your advanced TS course? Also, I tried following you on Mastodon but it looks like you never post there.

  • @mattpocockuk

    @mattpocockuk

    Жыл бұрын

    The first module is out! totaltypescript.com

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

    Yes I kind of wish there was a lint to enforce enum assignments (e.g DEBUG = ‘DEBUG’, actually now that I think about it there probably is a lint for this somewhere out there). I think enums are great for making your code more searchable.

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

    Is it worth to call Object.freeze() on a const asserted enum? A const asserted enum is a compile-time only check and freezing an object will guarantee that an object cannot be modified on a shallow level during runtime.

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

    i wonder how these "as const" alternatives work in serialization. and if they're supported by major API frameworks (like swagger for example) guess i'll test it out...

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

    We were using Enums in my previous project and weird things were happening during runtime. Thanks for showing a simple clean solution. I wish I could go back and fix all those Enums 😓

  • @magfal

    @magfal

    Жыл бұрын

    Its the fault of JS, not Enums. They are a very useful tool in production grade languages.

  • @alguienmasraro915

    @alguienmasraro915

    Жыл бұрын

    @@magfal More likely it's the fault of developers using enums as values as not as what they are: flags.

  • @Luxcium
    @Luxcium11 ай бұрын

    I feel like if Enums add something to the JavaScript side from the TypeScript side and I never have been happy about it… I realized that without thinking about it just because I was having all my types and interfaces in one same folder and Enum kind of needed to be in that folder and outside of it at a same time

Келесі