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

Template Literal Types în TypeScript: Cum am mapat permisiunile fără typo-uri

De Gabriela Neagu, 28 mai 2026 · 8 vizualizări · 2 like-uri

Postat 28 mai 2026
typescript
type Resource = 'users' | 'posts' | 'billing';
type Action = 'read' | 'create' | 'update' | 'delete';

// Generăm dinamic toate combinațiile de permisiuni permise
type Permission = `api:${Resource}:${Action}`;

interface User {
  id: string;
  permissions: Permission[];
}

function hasPermission(user: User, permission: Permission): boolean {
  return user.permissions.includes(permission);
}

const user: User = {
  id: 'dev-42',
  permissions: ['api:users:read', 'api:posts:create']
};

// Compilează perfect:
hasPermission(user, 'api:users:read');

// Eroare la compilare: Argument of type '"api:users:destroy"' is not assignable to...
// hasPermission(user, 'api:users:destroy');

Am lucrat recent la refactorizarea unui sistem de autorizare pentru un client cu vreo 120 de endpoint-uri și 14 resurse diferite. Inițial, permisiunile erau doar niște string-uri simple salvate în baza de date și verificate prin cod cu clasicul if (user.hasPermission('api:users:write')). Evident, pe măsură ce echipa a crescut, au început să apară typo-urile în cod: ba un user:write în loc de users:write, ba un api:reports:get în loc de read.

Când ai de-a face cu un codebase mare, string-urile simple folosite pe post de ID-uri de permisiuni sunt o bombă cu ceas. TypeScript ne oferă însă o unealtă excelentă pentru a rezolva asta direct la nivel de compilator: template literal types.

De ce ne batem capul cu asta?

Scopul a fost simplu: dacă un developer scrie greșit o permisiune în cod, vreau ca IDE-ul să urle instant, nu să prindem bug-ul în producție când vreun client își dă seama că nu-și poate descărca rapoartele financiare.

Template literal types funcționează exact ca template literals din JavaScript, dar la nivel de sistem de tipuri. Ele ne permit să combinăm tipuri de tip string union pentru a genera automat noi seturi de string-uri permise.

Noi avem un monorepo unde share-uim tipurile astea între backend-ul de Node.js și frontend-ul de React. Când backend-ul adaugă o resursă nouă în uniune, frontend-ul primește automat erori la compile time dacă nu a tratat noua structură sau dacă folosește permisiuni învechite.

Cum se construiește tipizarea strictă

În loc să scriem manual sute de combinații de permisiuni, definim doar blocurile de bază. Avem resursele sistemului și acțiunile pe care le poate face un utilizator pe acele resurse. Prin interpolare, TypeScript va genera automat produsul cartezian dintre aceste două mulțimi de string-uri.

Partea mișto e că funcția de verificare primește acum un tip ultra-specific. Autocomplete-ul în VS Code devine o plăcere. Începi să scrii api: și primești instant lista completă de variante valide. Nu mai trebuie să cauți prin fișierele de configurare ca să vezi dacă era read sau get.

Trade-off-ul de care te lovești la scară mare

Totul sună perfect pe hârtie, dar există un revers al medaliei pe care l-am simțit pe pielea noastră. TypeScript generează aceste tipuri în memorie prin recursivitate și combinatorică.

Dacă ai 20 de resurse și 5 acțiuni, rezultă 100 de combinații. E floare la ureche pentru compilator. Însă, dacă vrei să adaugi și un al treilea nivel de granularitate (de exemplu: api:${Resource}:${Action}:${Scope} unde scope-ul poate fi own, group sau all), numărul de combinații explodează exponențial.

La proiectul nostru, când am încercat să fim prea stricți și să includem și regiunile geografice în tip, ne-am trezit rapid cu celebra eroare Expression produces a union type that is too complex to represent. Mai mult, timpul de build pe pipeline-ul de CI/CD crescuse cu aproape 30% doar pentru că TypeScript se chinui să rezolve zeci de mii de combinații de string-uri în background. Am rezolvat-o simplificând structura și păstrând doar nivelurile macro în tipuri.

Cum gestionați voi permisiunile complexe în TypeScript? Mergeți pe tipizare strictă de genul ăsta sau lăsați verificarea doar în runtime pe baza unui fișier JSON de configurare?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

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