Ce face index signatures
Uneori nu știi dinainte numele proprietăților: un dicționar oraș → populație, note pe materii, setări citite dintr-un fișier. O index signature descrie astfel de obiecte: [cheie: string]: number înseamnă „orice cheie text, cu valoare număr”. Cheia poate fi string, number, symbol sau un template literal ([k: `data-${string}`]: string).
Record<string, number> este forma scurtă pentru același lucru și se citește mai ușor. Cu un union de literale în loc de string, Record<"lei" | "euro", number>, obiectul trebuie să aibă exact acele chei (vezi Record). Pentru dicționare care se modifică des, Map<string, number> este adesea o alegere mai bună.
Atenție: tipul spune că dictionar["orice"] este number, chiar dacă cheia nu există și valoarea este de fapt undefined. Opțiunea noUncheckedIndexedAccess adaugă undefined la tipul citit, ca să fii obligat să verifici. Proprietățile cu nume fix scrise lângă o index signature trebuie să aibă un tip compatibil cu ea.
Exemple
Exemplul 1: Dicționar cu chei text
interface Populatie {
[oras: string]: number;
}
const populatie: Populatie = { "Iași": 271692, "Cluj-Napoca": 286598 };
populatie["Timișoara"] = 250849;
for (const [oras, locuitori] of Object.entries(populatie)) {
console.log(oras.padEnd(12), locuitori.toLocaleString("ro-RO"));
}
console.log("Brașov" in populatie, populatie["Brașov"]);
Rezultat
Iași 271.692
Cluj-Napoca 286.598
Timișoara 250.849
false undefined
Exemplul 2: Record și numărarea cuvintelor
Record<string, number> este echivalent cu { [cheie: string]: number }. ?? 0 tratează cheile care încă nu există.
function numara(text: string): Record<string, number> {
const rezultat: Record<string, number> = {};
for (const cuvant of text.toLowerCase().split(/\s+/)) {
rezultat[cuvant] = (rezultat[cuvant] ?? 0) + 1;
}
return rezultat;
}
console.log(numara("Ana are mere și Ana are pere"));
Rezultat
{ ana: 2, are: 2, mere: 1, 'și': 1, pere: 1 }
Exemplul 3: Proprietate fixă incompatibilă cu index signature
Toate valorile trebuie să fie number, inclusiv proprietatea cu nume fix moneda.
interface Preturi {
moneda: string;
[produs: string]: number;
}
const p: Preturi = { moneda: "lei", paine: 5 };
console.log(p);
Eroarea afișată de tsc
exemplu.mts(2,5): error TS2411: Property 'moneda' of type 'string' is not assignable to 'string' index type 'number'.
exemplu.mts(5,7): error TS2322: Type '{ moneda: string; paine: number; }' is not assignable to type 'Preturi'.
Property 'moneda' is incompatible with index signature.
Type 'string' is not assignable to type 'number'.
Greșeli frecvente
- Folosești
{ [k: string]: any }pentru orice obiect. Pierzi toată verificarea; descrie proprietățile cunoscute. - Crezi că
note["fizică"]este sigur pentru că are tipulnumber. Cheia poate lipsi; verifică cuinsau??.
Comenzi înrudite
Record: Record<K, T> descrie un obiect ale cărui chei sunt K și ale cărui valori au toate tipul T.interface: Descrie forma unui obiect: ce proprietăți are, de ce tip sunt și ce metode are.mapped types: Construiesc un tip nou trecând prin fiecare cheie a altui tip: { [K in keyof T]: … }.keyof: keyof T dă union-ul numelor de proprietăți ale lui T, de exemplu „nume” | „oras”.