Master nominal branded typing techniques to prevent accidentally passing raw unvalidated strings or IDs to domain functions.
Discover how TypeScript infers types automatically and how let versus const declarations shape wide types versus narrow literal types.
TypeScript uses a Structural Type System (duck typing). If two types share the same structure, they are considered compatible, even if they have different intent (e.g. UserId and ProductId both being string).
A Branded Type (or Nominal Type) attaches a unique, phantom compile-time "brand" tag to a primitive type to ensure different domain identifiers cannot be accidentally swapped!
// Unique brand tag trick
declare const __brand: unique symbol;
type Brand<T, K extends string> = T & { readonly [__brand]: K };
// Define nominal domain types!
type UserId = Brand<string, "UserId">;
type ProductId = Brand<string, "ProductId">;
// Constructor helper functions (Smart Constructors)
function makeUserId(id: string): UserId {
return id as UserId;
}
function makeProductId(id: string): ProductId {
return id as ProductId;
}
function fetchUserProfile(userId: UserId) {
console.log("Fetching profile for:", userId);
}
const uId = makeUserId("usr_101");
const pId = makeProductId("prod_999");
fetchUserProfile(uId); // Valid!
// fetchUserProfile(pId); // Error: Type 'ProductId' is not assignable to type 'UserId'!
// fetchUserProfile("raw_string"); // Error: Type 'string' is not assignable to 'UserId'!
USD vs EUR, UserId vs OrderId) where mixing primitives causes severe financial or data corruption bugs!Use branded types for domain IDs and monetary units. Next, let me explain Strict Compiler Flags in tsconfig.json!