Enums considered harmful

  Рет қаралды 192,744

Matt Pocock

Matt Pocock

Жыл бұрын

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

Пікірлер: 477
@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
@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.
@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.
@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 KZbin video ❤
@ThijmenCodes
@ThijmenCodes Жыл бұрын
Hey Matt, I like how you express yourself. Well-paced and with plenty of depth without getting long-winded. Awesome!
@mohsinammar5070
@mohsinammar5070 2 күн бұрын
As a senior typescript developer, this shows that you have actually worked in production for a long time. A lot of KZbin channels pretend to teach you cool stuff but enterprise-grade apps are so different. This exact reason you showed is actually why I have stopped using these myself. I mean I'm working on the enterprise level of a web app, where our codebase is being maintained by 6 teams for just the front end and these issues are common with enterprise-level apps.
@artu-hnrq
@artu-hnrq 11 ай бұрын
My Typescript understanding has improved a lot since I started to watch your videos, Matt. Thanks for that
@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 8 ай бұрын
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.
@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 11 ай бұрын
you can just type. enum LogLevelEnum { debug = 'DEBUG', warning = 'WARNING', error = 'ERROR', } let logLevel: LogLevelEnum = LogLevelEnum.debug
@orlantquijada
@orlantquijada Жыл бұрын
commenting to support the channel. loving the content lately, hopefully more to come!
@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.
@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!
@xbsidesx
@xbsidesx Жыл бұрын
Nice, your approach explaining things is really objective and I love the pacing of the whole video. Thank you!
@iterativeincremental
@iterativeincremental Жыл бұрын
without the re-enacting of 'hey maccarena' by the hands: One of the better instructional videos on ts i have seen.
@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
@RyanTipps
@RyanTipps 10 ай бұрын
such an underrated channel - thank you so much!
@therufa
@therufa Жыл бұрын
i like the `keyof typeof` solution the most ❤ it's just so simple and versatile. Nice vod!
@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.
@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 9 ай бұрын
ran*
@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?
@juancarlosqr
@juancarlosqr Жыл бұрын
I wasn't even aware of this pitfalls of the enum, thanks!
@Johnny-rn8fb
@Johnny-rn8fb Жыл бұрын
very rarely such quality content
@tomermatmon
@tomermatmon Жыл бұрын
This video doesn't deserve a like - it deserves a love button! Thanks!
@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.
@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.
@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.
@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.
@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 kzbin.info/www/bejne/oJuwk4OqlK1miLM
@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?
@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?
@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];"
@olduniverse9270
@olduniverse9270 Жыл бұрын
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.
@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
@yolamontalvan9502
@yolamontalvan9502 10 ай бұрын
Professor, This what I was looking for. Thanks. I subscribed.
@StuartLoria
@StuartLoria 3 ай бұрын
His british-english is american-english friendly, and he makes things clear, which is a first from a skinny smart guy, well done Sir.
@jacoobes
@jacoobes Жыл бұрын
Could you argue that something like tsup which automatically inlines enums if possible and bitfields are good arguments for enum usage?
@whitefluffycloud
@whitefluffycloud Жыл бұрын
Thanks for explaining the IIFE joke to us. That totally made it much better... XD
@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.
@laesseV
@laesseV Жыл бұрын
What do you think about the upcoming typescript 5.0 enum unification?
@eXquisiteBuddy
@eXquisiteBuddy 6 ай бұрын
Swift has a really cool thing where when you press '.' and the definition expects an enum you get the autocomplete.
@GustavoDiaz93
@GustavoDiaz93 Жыл бұрын
Where can I watch the interview you mention ate the beginning of the video?
@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.
@wfl-junior
@wfl-junior Жыл бұрын
8:53, don't need to exit fullscreen, you can scroll down in fullscreen mode :)
@switzerland
@switzerland Жыл бұрын
Oh wow, that why I had such an initial pain with TS, that explains a lot 😮
@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.
@Luxcium
@Luxcium 11 ай бұрын
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
@OP-tw6bf
@OP-tw6bf 10 ай бұрын
Is there a tslint warning that you can use to discourage enums?
@Joso997
@Joso997 Жыл бұрын
I am using enums for my whole framework. They are perfectly fine
@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
@balogunakanbi6329
@balogunakanbi6329 Жыл бұрын
Can this be used to replace library code for enums?
@Gruby7C1h
@Gruby7C1h Жыл бұрын
Any link to interview with Anders you've mentioned?
@arber10
@arber10 10 ай бұрын
Didn‘t even need to remove the fullscreen to press 👍🏻. Thanks!
@KevinBoosten
@KevinBoosten Жыл бұрын
IIFE 🤣. Great video again! And completely agree with you that enums add little value (but more size) to your codebase 🎉
@AKrieger94
@AKrieger94 Жыл бұрын
Thanks, love your content!
@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.
@Nemhesis10
@Nemhesis10 Жыл бұрын
I just want to know how to export it?, Cause if I export the type after the const is't working...
@codevincas
@codevincas Жыл бұрын
What about the case when enum value is used as a type: export type State = | { name: AuthState.Loading } | { name: AuthState.Error; message: string } Using string literal in `name` doesn't let me keep a single source of truth, but the alternative with `as const` seems to be `typeof AUTH_STATE.LOADING` which seems pretty convoluted. Could also extract the type, but it's also not pretty: type AuthStates = typeof AUTH_STATE export type AuthState = | { name: AuthStates['LOADING'] } | { name: AuthStates['ERROR'], message: string }
@MK-bx8xv
@MK-bx8xv Жыл бұрын
3:15 it does work for regular numeric enums.
@galaxy9689
@galaxy9689 Жыл бұрын
how should i type enums that are like this export enum DisableType { TEST1 = 22, TEST2 = 23, }
@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.
@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.
@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.
@JosephDalrymple
@JosephDalrymple 4 ай бұрын
I feel like this could be solved by disabling enumerability on the reverse map keys of the enum. At that point, you could still reverse lookup, but you could also still iterate through the keys.
@je12emy
@je12emy Жыл бұрын
Awesome video, thank you so much!
@EverydayJavaScript
@EverydayJavaScript Жыл бұрын
Amazing video Matt... Thanks...
@csupakabra4
@csupakabra4 9 ай бұрын
So what exactly is the advantage of obect as const over string enum?
@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.
@YeloPartyHat
@YeloPartyHat 5 ай бұрын
Going through all your videos. I had no idea about those runtime qwerks!
@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.
@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...
@aprilmintacpineda2713
@aprilmintacpineda2713 Жыл бұрын
I would just use a string literal for that, like, “debug” | “warn” etc
@user-ui2ko1ob5y
@user-ui2ko1ob5y 5 ай бұрын
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.
@yolamontalvan9502
@yolamontalvan9502 10 ай бұрын
I usually use const in upper case to create words used as words in C+. Works for me. In C#, I use enums.
@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..😉
@paulsanchez5030
@paulsanchez5030 11 ай бұрын
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.
@quantum_dongle
@quantum_dongle 10 ай бұрын
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.
@jtw-r
@jtw-r Жыл бұрын
ok … i’ve unknowingly run into this problem before, and also came to the conclusion that enums can product slightly less readable code (the double access). only occurred once or twice.
@Mi2ey
@Mi2ey 10 ай бұрын
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!
@JamesQQuick
@JamesQQuick 3 ай бұрын
Great video!
@David-oc8yt
@David-oc8yt 4 ай бұрын
Coming from a C++ background, and given the described potential security issues with const, I much prefer the default implementation (non-const enum)
@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.
@loko1944
@loko1944 Жыл бұрын
what when I get backend status in number?
@denisonnunes1187
@denisonnunes1187 5 ай бұрын
Do you think about fixing the enum problem in the td-reset library
@mattpocockuk
@mattpocockuk 5 ай бұрын
It's not really something we can touch because ts-reset only looks at global typings, not runtime behaviour.
@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.
@code-island
@code-island Жыл бұрын
This is Amazing Matt, keep bringing this day to day useful tips in typescript
@dickheadrecs
@dickheadrecs Жыл бұрын
why doesnt the compiler use a Map and polyfill it for es5 & es3?
@petarkolev6928
@petarkolev6928 Жыл бұрын
Omg, "as const" really sounds as a killer :O Thank you, Matt!!!!!!!!!!!!
@thiagoalmeida5437
@thiagoalmeida5437 10 ай бұрын
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
@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
@ivanrenescorcia
@ivanrenescorcia Жыл бұрын
Really like it!
@mocastello9253
@mocastello9253 8 ай бұрын
great video! thank you!
@michaelpumo83
@michaelpumo83 10 ай бұрын
What’s the advantage of a POJO with “as const” over something like a union of strings?
@mattpocockuk
@mattpocockuk 10 ай бұрын
Because you have it as a value, so you do things like Object.values etc.
@user-kt7li4le8s
@user-kt7li4le8s 11 ай бұрын
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 😅
@pepew7102
@pepew7102 Жыл бұрын
I don't get how enums can be used at runtime. It's a typescript feature right ?
@FelipeMaffezzolli
@FelipeMaffezzolli Жыл бұрын
Thanks!
@scaredphoenix945
@scaredphoenix945 Жыл бұрын
You can even make it immutable and no need to do 'as const' casting: export const StatusResponse = Object.freeze({ Ok: 0, PartiallyFailed: 1, Failed: 2 }); And do a type alias: export type StatusResponse = typeof StatusResponse[keyof typeof StatusResponse];
@kasperaamodt
@kasperaamodt Жыл бұрын
I had 1 enum for languages in my new app, just refactored to const as const! 😁
@mattpocockuk
@mattpocockuk Жыл бұрын
Woohoo!
@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.
@iAmTheWagon
@iAmTheWagon Жыл бұрын
The dad joke at 2:38 made me immediately like and subscribe :)
Infer is easier than you think
13:38
Matt Pocock
Рет қаралды 85 М.
Building a type-safe fetch in #typescript
1:00
Matt Pocock
Рет қаралды 26 М.
New Gadgets! Bycycle 4.0 🚲 #shorts
00:14
BongBee Family
Рет қаралды 15 МЛН
Ну Лилит))) прода в онк: завидные котики
00:51
Каха инструкция по шашлыку
01:00
К-Media
Рет қаралды 7 МЛН
Wide vs Narrow Types #typescript
0:54
Matt Pocock
Рет қаралды 15 М.
What is tRPC? #typescript
0:50
Matt Pocock
Рет қаралды 26 М.
TypeScript - The Basics
12:01
Fireship
Рет қаралды 1,5 МЛН
Learn nested interfaces in typescript within 2 minutes 🙂🚀!
3:11
Don't put your types in .d.ts files
3:54
Matt Pocock
Рет қаралды 127 М.
React is going to change SO MUCH in 2024 #react
0:54
Matt Pocock
Рет қаралды 62 М.
TypeScript vs ESLint #typescript #javascript
0:58
Matt Pocock
Рет қаралды 15 М.
Apple Intelligence Is Here: What Can It Do?
6:10
Two Minute Papers
Рет қаралды 22 М.
Return Types vs Inference #typescript
0:57
Matt Pocock
Рет қаралды 17 М.
I Cannot Believe TypeScript Recommends You Do This!
7:45
Web Dev Simplified
Рет қаралды 159 М.
Панда 🐼🤣❤️
0:58
Dragon Нургелды 🐉
Рет қаралды 1,9 МЛН
Mom VS Сockroach🤭🪳 Who'll eat the noodles faster? #food
0:23
Funny kid and Dad #shorts #funny #viral #comedy #youtubeshorts
0:15
mountainlion5
Рет қаралды 96 МЛН