Shrink TypeScript Code: Replace Enums with Const Objects
A Smarter Way to Handle Enumerations in TypeScript
Why Enums Cause Problems
Enums look elegant, but they secretly bloat your JavaScript output. Each one compiles into a function wrapper that adds unnecessary weight to your bundle.
Example:
// Old way with enums
enum PaymentMethod {
Credit = 'credit',
Debit = 'debit',
Cash = 'cash',
}
Usage:
const method = PaymentMethod.Credit;
After compilation:
var PaymentMethod;
(function (PaymentMethod) {
PaymentMethod["Credit"] = "credit";
PaymentMethod["Debit"] = "debit";
PaymentMethod["Cash"] = "cash";
})(PaymentMethod || (PaymentMethod = {}));
Each key creates more boilerplate. In large projects with dozens of enums, this overhead adds up.
A Better Approach: Const Objects + Type Aliases
Replace enums with const objects and a type alias for keys.
// Modern way
const PaymentMethod = {
Credit: 'credit',
Debit: 'debit',
Cash: 'cash',
} as const;
type PaymentMethod = keyof typeof PaymentMethod;
const method: PaymentMethod = PaymentMethod.Credit;
✅ Still type-safe
✅ Works with IntelliSense
✅ Generates minimal JavaScript
Real-Life Examples
1. Form States
// Const object version
const FormStatus = {
Idle: 'idle',
Submitting: 'submitting',
Success: 'success',
Error: 'error',
} as const;
type FormStatus = keyof typeof FormStatus;
function renderForm(status: FormStatus) {
console.log(`Form is ${status}`);
}
renderForm(FormStatus.Success); // ✅ Auto-complete works
2. Application Themes
const AppTheme = {
Light: 'light',
Dark: 'dark',
System: 'system',
} as const;
type AppTheme = keyof typeof AppTheme;
function applyTheme(theme: AppTheme) {
console.log(`Theme applied: ${theme}`);
}
applyTheme(AppTheme.Dark);
3. HTTP Responses
const HttpResponse = {
Ok: 200,
NotAuthorized: 401,
Timeout: 408,
} as const;
type HttpResponse = typeof HttpResponse[keyof typeof HttpResponse];
if (res.code === HttpResponse.Timeout) {
console.error('Request timed out');
}
Special Cases
Numeric Codes
const Signal = {
Start: 1,
Stop: 2,
Pause: 3,
} as const;
type Signal = typeof Signal[keyof typeof Signal];
Reverse Lookup
If you need reverse mapping, write a helper:
function findKey<T extends Record<string, unknown>>(
obj: T,
value: T[keyof T]
): string | undefined {
return Object.keys(obj).find((k) => obj[k] === value);
}
const found = findKey(HttpResponse, 401); // "NotAuthorized"
Results After Migration
Before: 1.1MB bundle, 20 enums
After: 880KB bundle, 0 enums
That’s a 20% reduction with no loss of developer experience.
Final Thoughts
Enums aren’t always bad, but in most cases, const objects with type aliases:
Keep type safety
Preserve autocomplete
Generate cleaner JavaScript
Reduce bundle size
If you don’t need reverse mapping, ditch enums.
That's the way to go, I don't remember the last time I used enum
One extra step that I do for such objects is `Object.freeze` to make them truly immutable