eduardweb.
TypeScript avansatAvansat#architecture#typescript#type-safety#webdev

Cum m-au salvat Template Literal Types de bug-urile de permisiuni în producție

De Ștefan Iliescu, 18 iul. 2026 · 12 vizualizări · 3 like-uri

Postat 18 iul. 2026
typescript
type Resource = "users" | "posts" | "billing";
type Action = "create" | "read" | "update" | "delete";

// Magia se întâmplă aici
type Permission = `api:${Resource}:${Action}`;

// Un exemplu de funcție care consumă acest tip
function hasPermission(userPermissions: Permission[], required: Permission): boolean {
  return userPermissions.includes(required);
}

// Utilizare corectă
const myPermissions: Permission[] = ["api:users:read", "api:billing:update"];
hasPermission(myPermissions, "api:users:read"); // OK

// Eroare detectată instant la compile-time!
// @ts-expect-error
hasPermission(myPermissions, "api:user:read");

Cum am trecut de la string-uri oarbe la tipuri stricte

La un proiect început acum doi ani, un SaaS în zona de fintech cu vreo 8.000 de utilizatori activi, aveam clasica problemă a permisiunilor. Verificările arătau cam așa: if (hasPermission(user, "billing:write")). Toate bune și frumoase, până când un coleg a scris din greșeală "biling:write" (cu un singur „l”) într-un controller critic. Codul a trecut de review, testele unitare nu acopereau exact acea ramură, iar clientul s-a trezit că nu poate plăti factura.

Atunci mi-am dat seama că trebuie să lăsăm compilerul să își facă treaba. Template literal types, introduse prin TypeScript 4.1, sunt exact unealta de care aveam nevoie pentru a transforma string-urile în API-uri sigure.

Sintaxa care combină tipurile ca pe string-uri

Ideea e simplă. În loc să definim manual o listă uriașă de string-uri permise, lăsăm TypeScript să genereze toate combinațiile posibile prin interpolare. Declarăm resursele și acțiunile, iar apoi le unim.

Dacă cineva încearcă să folosească o permisiune invalidă, TypeScript va arunca o eroare direct în IDE înainte ca acel cod să ajungă măcar în staging. Autocomplete-ul devine brusc o plăcere: scrii api: și IDE-ul îți sugerează instant toate combinațiile valide.

Trade-off-ul ascuns: când compile-time devine coșmar

Totuși, nu totul e lapte și miere cu abordarea asta. Am învățat pe pielea mea că template literal types vin cu un cost serios de performanță dacă exagerezi.

TypeScript generează un produs cartezian în spate. Dacă ai 50 de resurse și 10 acțiuni posibile, compilerul trebuie să gestioneze 500 de tipuri unice. La proiectul nostru, când am încercat să adăugăm și ID-uri dinamice în template-uri (de genul api:${Resource}:${ID}:${Action}), VS Code pur și simplu a înghețat. Build time-ul în CI a crescut cu aproape 40%, iar colegii se plângeau că analiza statică durează secunde bune la fiecare salvare de fișier.

Regula de aur pe care am descoperit-o? Păstrează seturile de date cât mai mici și nu încerca să mapezi ID-uri dinamice sau UUID-uri direct în template literals la nivel de tip. Folosește tipuri generice doar pentru structura de bază a permisiunilor.

Cum facem cu datele din baza de date?

O altă problemă de care ne-am lovit a fost parsarea datelor venite din API sau DB. Acolo primești un string chior. Pentru a le mapa în siguranță pe tipul nostru strict, am folosit un Type Guard simplu. Ne asigurăm la granița aplicației că datele respectă formatul, iar apoi în interiorul codului ne bucurăm de type safety deplin.

Voi cum gestionați permisiunile în aplicațiile mari? Mergeți pe tipare stricte în TypeScript sau preferați flexibilitatea string-urilor simple, lăsând validarea exclusiv în runtime?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.