Deoarece TypeScript folosește un sistem de tipare structurală, dacă două variabile au tipul primitiv string sau number, ele sunt considerate 100% interschimbabile de compilator. În practică, aceasta este sursa unor bug-uri de producție extrem de subtile: transmiterea accidentală a unui orderId într-o funcție care aștepta un userId, sau adunarea unei sume în EUR cu o sumă în RON fără conversie valutară.
Tehnica Branded Types (cunoscută și ca Nominal Typing sau Type Flavoring) atașează o „marcă” unică invizibilă la nivelul compilatorului pentru a face tipurile primitive incompatibile structural între ele.
// PERICOL: Fără Branded Types
function anuleazaComanda(orderId: string, userId: string) { ... }
const uid = "usr_123";
const oid = "ord_999";
anuleazaComanda(uid, oid); // COMPILĂ FĂRĂ EROARE! Parametrii au fost inversați, dar ambii sunt 'string'!
// SOLUȚIA CU BRANDED TYPES:
declare const BrandSimbol: unique symbol;
type Brand<T, NumeBrand> = T & { readonly [BrandSimbol]: NumeBrand };
type UserId = Brand<string, 'UserId'>;
type OrderId = Brand<string, 'OrderId'>;
// Funcții de validare și construcție sigură (Smart Constructors):
function creazaUserId(id: string): UserId {
if (!id.startsWith("usr_")) throw new Error("ID utilizator invalid!");
return id as UserId;
}
function creazaOrderId(id: string): OrderId {
if (!id.startsWith("ord_")) throw new Error("ID comandă invalid!");
return id as OrderId;
}
function anuleazaComandaSigur(orderId: OrderId, userId: UserId) {
console.log(`Anulare comanda ${orderId} a utilizatorului ${userId}`);
}
const idUserValid = creazaUserId("usr_123");
const idComandaValid = creazaOrderId("ord_999");
// anuleazaComandaSigur(idUserValid, idComandaValid);
// EROARE DE COMPILARE IMEDIATĂ!
// Type 'UserId' is not assignable to type 'OrderId'.
Cazuri Esențiale de Utilizare în Sisteme Financiare și de Securitate
- Monede și Finanțe: Diferențierea tipurilor
type SumaRON = Brand<number, 'RON'>șitype SumaEUR = Brand<number, 'EUR'>. Împiedică adunarea eronată a două sume fără apelarea ratei de schimb. - Date Sanitize / Securitate: Diferențierea unui șir brut primit de la utilizator de un șir sanitizat împotriva atacurilor XSS:
type HtmlSanitizat = Brand<string, 'SafeHtml'>. Funcția de render acceptă exclusivHtmlSanitizat. - Performanță: Nu există zero overhead la runtime! Proprietatea de brand este doar o aserțiune pentru analizatorul de tipuri tsc și este complet eliminată (Type Erasure) în fișierul JavaScript final.