template literal types în TypeScript

Tipuri de text construite ca un template string: `id-${number}` acceptă "id-1", "id-42" și așa mai departe.

Sintaxă
type Id = `elev-${number}`;
type Eveniment = `on${Capitalize<"click" | "focus">}`;
type Css = `${number}px` | `${number}%`;

Ce face template literal types

Un template literal type se scrie ca un template string din JavaScript, dar între backtick-uri în poziție de tip. În locul valorilor pui tipuri: `elev-${number}` acceptă orice text care începe cu elev- urmat de un număr. Cu union-uri, se generează toate combinațiile: `${"mic" | "mare"}-${"rosu" | "albastru"}` are patru variante.

Se combină cu tipurile pentru text Uppercase, Lowercase, Capitalize, Uncapitalize, cu mapped types (pentru a redenumi chei) și cu infer (pentru a desface texte).

Sunt utile pentru nume de evenimente (onClick), chei CSS, rute, chei de traducere ("meniu.acasa") și id-uri cu prefix. Verificarea se face doar la compilare: un text venit din afară trebuie verificat la rulare.

Exemple

Exemplul 1: Id-uri cu prefix și unități CSS

type IdElev = `elev-${number}`;
type Marime = `${number}px` | `${number}rem` | "auto";

function stil(latime: Marime, inaltime: Marime): string {
    return `width: ${latime}; height: ${inaltime};`;
}

const id: IdElev = "elev-42";
console.log(id, stil("320px", "auto"));
console.log(stil("1.5rem", "48px"));

Rezultat

elev-42 width: 320px; height: auto;
width: 1.5rem; height: 48px;

Exemplul 2: Toate combinațiile dintr-un union

type Marime = "mic" | "mare";
type Culoare = "roșu" | "albastru";
type Varianta = `${Marime}-${Culoare}`;

const variante: Varianta[] = ["mic-roșu", "mic-albastru", "mare-roșu", "mare-albastru"];
const stoc: Record<Varianta, number> = { "mic-roșu": 3, "mic-albastru": 0, "mare-roșu": 5, "mare-albastru": 1 };

for (const v of variante) console.log(v.padEnd(14), stoc[v]);

Rezultat

mic-roșu       3
mic-albastru   0
mare-roșu      5
mare-albastru  1

Exemplul 3: Text care nu respectă forma

type IdElev = `elev-${number}`;
const a: IdElev = "elev-7";
const b: IdElev = "elev-sapte";
console.log(a, b);

Eroarea afișată de tsc

exemplu.mts(3,7): error TS2322: Type '"elev-sapte"' is not assignable to type '`elev-${number}`'.

Greșeli frecvente

  • Combini union-uri mari: 50 × 50 × 50 variante dau 125.000 de tipuri și tsc devine lent sau refuză (Expression produces a union type that is too complex to represent).
  • Crezi că `${number}` respinge "1e3" sau " 5". Regulile urmează conversia din JavaScript și pot accepta forme neașteptate.

Comenzi înrudite

  • tipuri literale: Un tip care acceptă o singură valoare exactă, de exemplu „Iași” sau 3; combinate în union dau liste de valori permise.
  • mapped types: Construiesc un tip nou trecând prin fiecare cheie a altui tip: { [K in keyof T]: … }.
  • infer: În ramura extends a unui tip condițional, infer X „prinde” o parte din tip și o dă un nume.
  • Uppercase: Uppercase<S> transformă un tip text în majuscule, Lowercase<S> în litere mici, la nivel de tip.
  • Capitalize: Capitalize<S> face prima literă a unui tip text mare; Uncapitalize<S> o face mică.