DEV Community

Cover image for The Code Review That Changed Everything

The Code Review That Changed Everything

Elvis Sautet on October 20, 2025

Three months ago, I submitted what I thought was a perfectly reasonable pull request. I had created a new UserRole enum to handle our permission sy...
Collapse
 
himanshu_code profile image
Himanshu Sorathiya

Haha
Ive a funny story about enums
While learning TS, as all suggest "see TS compiled code into JS" to see how and what it compiled to.
And as beginner curiosity I also did that at that time, and seeing TS code into JS, I was said everything TS related things will be reversed like types, etc. And it was true every TS annotations were not in compiled JS.
Then I learnt about enums and when it converted to JS, I did not expected that, was seeing an IIFE function, all I knew that time was TS should convert it to be in compiled time thing but IIFE funcs are runtime, and also couldnt comprehend how things were "working" in that function, so just for "i did not understand working of that thing" i switched the road and took "objects as const" and put "enums" on sideways as future topic but from then ive never needed to use enums

I still find this funny, a simple not understanding of working of enums from TS to JS transfered me to whole new path

Collapse
 
n3nad profile image
Nenad Mitrovic

It's funny how, as we progress in our careers, we always encounter uncharted territory within JavaScript/TypeScript's complex abstractions. At first it feels discouraging - until you consider how JavaScript enabled over a billion web and mobile projects that would otherwise never exist. Then you implement that fix, wake up the next morning, and suddenly everything feels right with the world again. ✨

Thanks for all the details!

Collapse
 
hashbyt profile image
Hashbyt

Fantastic deep dive and a crucial lesson for many TypeScript developers! The const object with as const pattern is undeniably superior for the reasons you've outlined.

I'm definitely making a point of using the pattern going forward: it ensures stricter literal typing and solves the tree-shaking problem completely. That side-by-side comparison of Numeric Enum Nightmare and the const object solution is perfect.

Collapse
 
alex_chen_3a43ce352a43d3d profile image
Alex Chen

this hits hard - especially the reverse mapping discovery. i had the exact same moment looking at compiled output and going "wait, why are we shipping TWO mappings for every numeric enum?"

the const enum trap is even more subtle though. you think you're being smart by using const enum to avoid the runtime code, but then you ship a library and suddenly your consumers can't use it because the values get inlined at compile time. breaks module boundaries in ways that aren't obvious until production.

one thing i'd add: the migration path matters. when you have 50+ enum usages across a codebase, switching to as const objects means updating every. single. reference. because the access pattern changes from Status.Active to staying the same BUT the type inference is different.

we ended up with a hybrid during migration: new code uses union types, legacy enums stay but with explicit // TODO: migrate comments. not perfect but beats a 3-day refactor that blocks feature work.

also the tree-shaking point is huge for libraries. we saved 2KB on our SDK bundle just by killing numeric enums. that's real bytes users download.

Collapse
 
elvissautet profile image
Elvis Sautet

The catch here is amazing

Collapse
 
aoda-zhang profile image
Aoda Zhang

Nice post,actually i have used enum many times,never considered what it will translated to js,great,i will change it to cost,thx

Collapse
 
holoflash profile image
Redas Jefisovas

Thanks for the super in-depth write up! I recently came to this understanding too and this is such a great resource if a discussion about enums ever comes up, and I need to make my case.

Collapse
 
byrni_68d699fd3b8533a73e7 profile image
Byrni

I don't agree. If you write enums like that I'd be asking you to change them back. You are trying to be clever by creating your own types rather than using the language as designed just to save a few kb at best. The typescript compiler can always be improved in the future to generate cleaner javascript, but if you write your code in a non standard format like this not only is the code less succinct but you miss out on those future updates to the compiler.

Collapse
 
kurealnum profile image
Oscar

Did not expect this to be so in depth. Do you think TypeScript enums themselves could/should be improved to prevent having to manually convert all of these (ex. some sort of flag/parameter/keyword for numeric enums that makes their use cases stricter)?

Collapse
 
cristian_fdbb0dc profile image
Cristian

To me better DX is worth the extra 12 KB. That kind of saving is negligible it’s like over-engineering with floats just to support the last % of IE users.

Collapse
 
josef_nymanmller_69e1d1 profile image
Josef Nyman Müller

Namespaces are fantastic if you have a big codebase and only use it for grouping types.

export declare namespace User {
interface Dto { id: string }
}

Then you can simply import {User} and use User.Dto. Instead of having to pollute your intellisense with a million types.

As long as you do it like this there are no downsides since the types are simply erased, so no issues with compilers, esmodules or tsconfig flags.

Collapse
 
neurolov__ai profile image
Neurolov AI

Eye-opening breakdown enums always felt off, but seeing the compiled output makes it undeniable. Love the const object + as const approach cleaner, safer and more JS-native.