
if (user.role === 2 && order.status === 7) {
applyDiscount(0.15);
}
What is role 2? What does status 7 mean? Why exactly 0.15? You have no idea without digging through the whole codebase or asking the original author.
These are magic numbers and magic strings — literal values dropped directly into logic with no explanation of what they represent. They're one of the most widespread code smells, and they sneak in gradually, one harmless-looking constant at a time.
Why they're a problem
2 means "admin role", that 2 appears in dozens of places. When the requirement changes, you have to find every single one — and hope you didn't miss any.
They break silently. If a magic string like "pending" is scattered across 10 files and a backend engineer renames the status to "awaiting", nothing fails at compile time. It just breaks at runtime, in production, on a Friday.
They create duplication. The same value gets typed in by different developers in different files. Now you have 0.15 as a discount in four places, and they drift out of sync over time.
They fail the "3am test". If you got woken up at 3am by a production bug and saw if (type === 4), would you know what to do?
What they look like in the wild
// ❌ What does any of this mean?
if (user.role === 2) { ... }
if (order.status === 7) { ... }
if (subscription.plan === 'pro_v2_monthly') { ... }
setTimeout(syncData, 86400000);
const fee = amount * 0.029 + 0.30;
if (response.code === 'ERR_INSUFFICIENT_FUNDS') { ... }
const MAX = 3; // three what? retries? attempts? items?Solution 1 — Named constants
// ✅ The name explains the intent
const ADMIN_ROLE_ID = 2;
const ORDER_STATUS_SHIPPED = 7;
const STRIPE_FIXED_FEE = 0.30;
const STRIPE_PERCENT_FEE = 0.029;
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
const MAX_RETRY_ATTEMPTS = 3;
// Now the code reads like a sentence
if (user.role === ADMIN_ROLE_ID) { ... }
setTimeout(syncData, ONE_DAY_MS);
const fee = amount * STRIPE_PERCENT_FEE + STRIPE_FIXED_FEE;ONE_DAY_MS = 24 * 60 * 60 * 1000 — keeping the math visible is better than writing 86400000. The calculation documents itself.
Solution 2 — Enums and const objects
// ✅ TypeScript enum
enum UserRole {
Guest = 1,
User = 2,
Moderator = 3,
Admin = 4,
}
enum OrderStatus {
Pending = 1,
Processing = 2,
Shipped = 7,
Delivered = 8,
Cancelled = 9,
}
// Usage
if (user.role === UserRole.Admin) { ... }
if (order.status === OrderStatus.Shipped) { ... }
// ✅ Or const object — better for tree-shaking in some setups
const PLAN = {
Free: 'free',
Pro: 'pro_v2_monthly',
Enterprise: 'enterprise',
} as const;
type Plan = typeof PLAN[keyof typeof PLAN];
if (subscription.plan === PLAN.Pro) { ... }UserRole.Admni, TypeScript tells you immediately. With 2, you're on your own.
Solution 3 — Centralised config for app-wide values
// config/constants.ts
export const PAYMENT = {
STRIPE_PERCENT_FEE: 0.029,
STRIPE_FIXED_FEE: 0.30,
MAX_REFUND_DAYS: 30,
} as const;
export const RETRY = {
MAX_ATTEMPTS: 3,
DELAY_MS: 1000,
BACKOFF_MULTIPLIER: 2,
} as const;
export const CACHE = {
USER_TTL_MS: 5 * 60 * 1000, // 5 minutes
SESSION_TTL_MS: 24 * 60 * 60 * 1000, // 24 hours
} as const;
// Anywhere in your app
import { PAYMENT, CACHE } from '@/config/constants';
const fee = amount * PAYMENT.STRIPE_PERCENT_FEE + PAYMENT.STRIPE_FIXED_FEE;
redis.set(key, value, 'PX', CACHE.USER_TTL_MS);The special case — magic strings in APIs
// ❌ A typo here causes a silent runtime bug
async function updateOrderStatus(id: string, status: string) {
// 'shiped' compiles fine, breaks at runtime
await orderRepo.update(id, { status });
}
// ✅ TypeScript catches the typo at compile time
type OrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
async function updateOrderStatus(id: string, status: OrderStatus) {
// 'shiped' is a compile error now — caught before it ships
await orderRepo.update(id, { status });
}Knowing when to leave a literal alone
// These are fine — the meaning is obvious from context
const isFirst = index === 0;
const isEmpty = items.length === 0;
const half = total / 2;
// These are magic — the meaning is not obvious
if (score >= 850) { ... } // 850 what? Why 850?
if (attempts > 3) { ... } // MAX_RETRY_ATTEMPTS = 3
if (role === 4) { ... } // UserRole.Admin