eduardweb.
TypeScript avansatAvansat#typescript#type-safety#advanced-ts

Cum am mapat 120 de permisiuni în TypeScript: Template Literal Types

De Ștefan Iliescu, 7 iul. 2026 · 15 vizualizări · 2 like-uri

Postat 7 iul. 2026
typescript
type Resource = 'user' | 'project' | 'billing';
type Action = 'read' | 'create' | 'update' | 'delete';

// Construim tipul dinamic de permisiune
type Permission = `api:${Resource}:${Action}`;

// Exemplu de utilizare într-o funcție de autorizare
function hasPermission(userPermissions: string[], required: Permission): boolean {
  return userPermissions.includes(required);
}

const userPermissions = ['api:user:read', 'api:project:create'];

// OK - compilează fără probleme
hasPermission(userPermissions, 'api:user:read');

// @ts-expect-error - eroare de compilare: 'api:users:read' (cu s) nu este valid
hasPermission(userPermissions, 'api:users:read');

Anul trecut am lucrat la un dashboard de admin pentru un client cu vreo 8k useri activi și un sistem de roluri destul de stufos. Aveam peste 120 de permisiuni de forma api:user:write sau billing:invoice:read. La început, toate erau doar string-uri simple lăsate la liber. Evident că am dat de clasica problemă: scria un coleg api:users:write (cu "s") în loc de api:user:write și ne trezeam cu bug-uri stupide în producție pe care le depistam doar când se plângea cineva.

Soluția a fost să migrăm totul pe template literal types. Ne-a salvat de o grămadă de boilerplate și am economisit cred că vreo 2 zile bune de debugging din start pentru că am prins greșelile de tipar chiar în timp ce scriam codul în editor.

Cum funcționează magia în practică

În TypeScript, template literal types îți permit să folosești sintaxa de template strings din JavaScript, dar direct în sistemul de tipuri. Practic, poți genera tipuri noi prin concatenarea altor uniuni de string-uri.

Imaginează-ți că ai trei resurse mari și late în aplicație și acțiunile standard de CRUD. În loc să scrii de mână fiecare combinație posibilă de permisiune într-un enum uriaș, le lași pe seama compilatorului. TypeScript va genera automat produsul cartezian dintre aceste mulțimi de string-uri.

Dacă ai Resource = 'user' | 'post' și Action = 'create' | 'delete', tipul ${Resource}:${Action} va deveni automat 'user:create' | 'user:delete' | 'post:create' | 'post:delete'. Fără efort suplimentar de mentenanță când adaugi o resursă nouă.

Trade-off-ul de care nu-ți spune nimeni

Să fim sinceri, nicio chestie de genul ăsta nu vine fără costuri. Template literal types sunt excepționale pentru autocompletion în IDE și pentru siguranța codului, dar au o mare problemă: performanța compilatorului din spatele scenei.

Dacă ai 10 resurse și 4 acțiuni, TS generează rapid 40 de tipuri în memorie. Dar dacă ajungi la 50 de resurse, 10 acțiuni și încă un wildcard pe la mijloc, ajungi imediat la mii de combinații. Am pățit la un moment dat să-mi crape TS Server în VS Code din cauza unei recursivități prea adânci în tipuri complexe. S-a blocat efectiv editorul și a trebuit să regândesc structura. Deci, folosește-le cu cap, nu încerca să mapezi tot internetul într-un singur tip generat dinamic.

De asemenea, tipurile astea există doar la faza de compilare. La runtime, tot trebuie să ai o metodă de validare reală pentru string-urile care îți vin din baza de date sau din token-ul JWT decodat.

Cum validăm la runtime fără să ne dublăm munca?

Cea mai curată abordare pe care am găsit-o este să folosesc o funcție de tip guard. Verificăm string-ul la runtime, iar TypeScript știe să facă type narrowing pe baza acelei verificări, oferindu-ne tipul strict în interiorul blocului conditonal.

Pentru asta, o funcție simplă de aserțiune sau un type guard rezolvă problema elegant. Practic, scrii o funcție care primește un string generic și returnează un boolean, având tipul de retur value is Permission. Astfel, dacă funcția întoarce true, compilatorul știe sigur că acel string poate fi folosit în siguranță ca o permisiune validă în restul aplicației.

Voi cum gestionați permisiunile complexe în proiectele mari? Mergeți pe tipuri stricte în TS sau lăsați totul în seama unui middleware la runtime și sperați că testele de integrare prind greșelile de tipar?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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