“Have you ever needed to display user-friendly labels, icons, or colors for numeric enums in TypeScript? Many devs either use switch statements or ad-hoc objects — but there’s a cleaner, type-safe way: Record.”
What is Record in TypeScript?
Short definition: Record is an object type with keys of type K and values of type T.
Think of it as a type-safe way to define “maps” from a known set of keys to specific values.
Here’s a very simple example using a union type:
// Union type of possible roles
type UserRole = "admin" | "user" | "guest";
// Record<UserRole, string> means:
// - keys must be "admin" | "user" | "guest"
// - values must be strings
const roles: Record<UserRole, string> = {
admin: "Administrator",
user: "Regular User",
guest: "Guest User",
};
// ✅ Safe lookup
console.log(roles.admin); // "Administrator"
// ❌ Error: TypeScript won’t let you add an unknown key
// roles.superAdmin = "Super Admin";
This ensures you don’t forget a key, and you can’t accidentally add extra ones.
Using Record with enums (real-world example)
Union types are nice, but in real-world projects we often work with enums. Let’s say you have an enum that represents payment statuses in your application:
enum PaymentStatus {
Unpaid = 0,
Paid = 1,
Failed = 2,
}
If you want to display labels and colors in your UI for each status, the naive way would be a bunch of switch statements. Instead, Record gives us a cleaner, safer approach:
const PaymentStatusMeta: Record<
PaymentStatus,
{ label: string; color: string }
> = {
[PaymentStatus.Unpaid]: { label: "Unpaid", color: "orange" },
[PaymentStatus.Paid]: { label: "Paid", color: "green" },
[PaymentStatus.Failed]: { label: "Failed", color: "red" },
};
Now, wherever you need metadata for a given status:
const status = PaymentStatus.Paid;
console.log(PaymentStatusMeta[status].label); // "Paid"
console.log(PaymentStatusMeta[status].color); // "green"
Helper function for cleaner usage
Instead of directly accessing PaymentStatusMeta every time, you can wrap it in a function:
function getPaymentStatusMeta(status: PaymentStatus) {
return PaymentStatusMeta[status];
}
// Usage
const info = getPaymentStatusMeta(PaymentStatus.Failed);
console.log(info.label); // "Failed"
console.log(info.color); // "red"
This makes the code more expressive and also helps if later you need to add logic (like localization or formatting) inside the function without touching the rest of your codebase.
Why use Record? (Advantages)
Using Record in TypeScript to map enums (or unions) to metadata brings several benefits:
Full coverage enforced by TypeScript
- TypeScript ensures that every key in your enum or union is included in the Record.
- Forgetting a case results in a compile-time error, preventing runtime bugs.
Strong type safety
- Values inside the Record must match the type you specify.
- No more accidentally assigning a string where an object is expected.
Extensible with metadata
- You can easily add more fields, like icon, tooltip, localeLabel, etc.
Cleaner than switch/case statements
- No repeated switch statements scattered across your codebase.
- Lookup is simple and readable: PaymentStatusMeta[status].label
Predictable and maintainable
- Future developers immediately know where to find mappings. Adding a new enum value only requires updating one place.
If you found this guide useful:
✅ Save it for future reference.
🔁 Share it with your team or developer friends.
💬 Comment below with your favorite TypeScript patterns or how you handle enum metadata in your projects.
Happy coding! 🚀




Very good 👍
Thanks