Ce face mapped types
Un mapped type creează un tip obiect parcurgând o listă de chei: { [K in Chei]: Tip }. Cel mai des cheile sunt keyof T, deci rezultatul are aceleași proprietăți ca T, dar cu alt tip sau alți modificatori. Așa sunt construite Partial, Required, Readonly, Pick și Record.
Modificatorii ? și readonly se pot adăuga (+?, +readonly sau doar ?) sau scoate (-?, -readonly). În interior, T[K] este tipul proprietății curente.
Cu as (TypeScript 4.1) poți redenumi cheile, de exemplu cu un template literal (`get${Capitalize<K>}`), sau le poți elimina: o cheie transformată în never dispare din rezultat.
Exemple
Exemplul 1: Toate proprietățile devin text pentru un formular
Câmpurile unui formular HTML sunt mereu text, indiferent de tipul datelor.
interface Elev {
nume: string;
varsta: number;
bursier: boolean;
}
type Formular<T> = { [K in keyof T]: string };
type Erori<T> = { [K in keyof T]?: string };
function valideaza(f: Formular<Elev>): Erori<Elev> {
const erori: Erori<Elev> = {};
if (f.nume.trim() === "") erori.nume = "Numele este obligatoriu";
if (!/^\d+$/.test(f.varsta)) erori.varsta = "Vârsta trebuie să fie un număr";
return erori;
}
console.log(valideaza({ nume: "Ana", varsta: "19", bursier: "da" }));
console.log(valideaza({ nume: " ", varsta: "nouăsprezece", bursier: "nu" }));
Rezultat
{}
{
nume: 'Numele este obligatoriu',
varsta: 'Vârsta trebuie să fie un număr'
}
Exemplul 2: Getter-e generate cu as
Fiecare cheie K devine getK cu prima literă mare, iar valoarea este o funcție.
type Getteri<T> = {
[K in keyof T as `get${Capitalize<K & string>}`]: () => T[K];
};
interface Oras {
nume: string;
populatie: number;
}
function cuGetteri(o: Oras): Getteri<Oras> {
return { getNume: () => o.nume, getPopulatie: () => o.populatie };
}
const iasi = cuGetteri({ nume: "Iași", populatie: 271692 });
console.log(iasi.getNume(), iasi.getPopulatie());
Rezultat
Iași 271692
Exemplul 3: Scoaterea lui readonly și a lui ?
interface Setari {
readonly limba?: string;
readonly tema?: string;
}
type Editabil<T> = { -readonly [K in keyof T]-?: T[K] };
const s: Editabil<Setari> = { limba: "ro", tema: "întunecată" };
s.tema = "luminoasă"; // permis: nu mai este readonly
console.log(s);
Rezultat
{ limba: 'ro', tema: 'luminoasă' }
Greșeli frecvente
- Uiți
& stringcând folosești cheia într-un template literal:keyof Tpoate conține șinumbersausymbol, iarCapitalizeacceptă doar text. - Scrii mapped type într-o
interface. Sintaxa[K in ...]funcționează doar în aliasuritype.
Comenzi înrudite
keyof: keyof T dă union-ul numelor de proprietăți ale lui T, de exemplu „nume” | „oras”.indexed access (T[K]): T[„cheie”] dă tipul unei proprietăți din T; T[number] dă tipul elementelor unui tablou.Partial: Partial<T> face toate proprietățile lui T opționale; util pentru actualizări în care trimiți doar ce se schimbă.Record: Record<K, T> descrie un obiect ale cărui chei sunt K și ale cărui valori au toate tipul T.template literal types: Tipuri de text construite ca un template string: `id-${number}` acceptă „id-1”, „id-42” și așa mai departe.conditional types: Un tip care alege între două variante după o condiție: T extends U ? X : Y.