Brand Your IDs: TypeScript’s Secret Weapon for Safer React Native Code
Learn how branded (opaque) types prevent ID mix‑ups in React Native projects, adding compile‑time safety without runtime overhead.
Insight
In many mobile apps, you’ll juggle several identifier strings—user IDs, order IDs, product IDs, etc. Accidentally passing a userId where a productId is expected can cause subtle bugs that only surface at runtime. TypeScript’s branded (or opaque) types let you create distinct compile‑time types for each ID while keeping the underlying value a plain string. This adds zero runtime cost but catches mismatches early in the IDE or CI pipeline.
Example
// Define a generic brand helper
type Brand<K, T> = K & { __brand: T };
// Create specific ID types
type UserId = Brand<string, "UserId">;
type ProductId = Brand<string, "ProductId">;
// Helper to cast safely
const asUserId = (id: string): UserId => id as UserId;
const asProductId = (id: string): ProductId => id as ProductId;
// Usage in a component
function fetchUserOrders(userId: UserId) {
// fetch logic …
}
const uid = asUserId('u_123');
const pid = asProductId('p_456');
fetchUserOrders(uid); // ✅ OK
// fetchUserOrders(pid); // ❌ TypeScript error
Takeaway
Adopt branded types for any identifier that travels through your app. They act as a lightweight contract, preventing accidental swaps and making refactors safer—all without affecting bundle size or performance.