Il tipo Record di TypeScript, spiegato con le tue chiavi
Tipo Record di TypeScript
TypeScript Record<K, V>: oggetti di lookup tipizzati spiegati | We.Inc
Crea un tipo Record<K, V> dalle tue chiavi e guarda l'oggetto che descrive. Scopri quando Record batte una index signature o una Map, e gli errori che intercetta.
Record<K, V> è un utility type integrato per un oggetto le cui chiavi provengono da K e i cui valori hanno tutti tipo V. Passagli una union di string literal e il compilatore pretende che ogni chiave elencata sia presente. Passagli un semplice string e si comporta come un dizionario aperto, esattamente come una index signature.
Record in sintesi
Scrivi
Significa
Chiave mancante consentita?
Record<"a" | "b", number>
{ a: number; b: number }
No, entrambe le chiavi obbligatorie
Record<string, number>
{ [key: string]: number }
Sì, qualsiasi chiave string
Partial<Record<"a" | "b", number>>
{ a?: number; b?: number }
Sì, ogni chiave facoltativa
Record<number, string>
{ [key: number]: string }
Sì, qualsiasi chiave number
Digita le chiavi che vuoi e scegli un tipo di valore. Il generatore scrive il tipo Record, il tipo oggetto semplice in cui si espande e un oggetto iniziale con una riga per chiave, così vedi esattamente cosa ti imporrà il compilatore prima di incollarlo nel tuo codice.
Digita le chiavi separate da virgole, ad esempio home, about, contact.
Scegli il tipo di valore che ogni chiave deve contenere.
Spunta facoltative se alcune chiavi possono mancare: il tipo viene racchiuso in Partial.
Copia il tipo e l'oggetto iniziale nel tuo file e compila i valori.
Ricava la union delle chiavi da dati che hai già: keyof typeof someObject o (typeof list)[number] dopo un array as const mantiene il Record allineato con la fonte.
Usa Record<string, T> solo quando le chiavi arrivano davvero a runtime. Una union chiusa intercetta gli errori di battitura nei nomi delle proprietà che un dizionario aperto lascia passare.
Attiva noUncheckedIndexedAccess se leggi da Record<string, T> con una chiave calcolata. Le letture restituiscono allora T | undefined, che corrisponde a ciò che succede a runtime.
Evita Record<string, any>. Record<string, unknown> accetta comunque qualsiasi oggetto ma ti obbliga a un controllo prima di usare un valore.
Domande frequenti
Record è la stessa cosa di una index signature?
Con una chiave ampia come string, sì: Record<string, number> e { [key: string]: number } descrivono la stessa forma. La differenza emerge con le chiavi letterali. Una index signature non può pretendere che esistano nomi specifici, mentre Record<"a" | "b", number> richiede sia a sia b.
Quando dovrei usare una Map invece di un Record?
Usa una Map quando le chiavi vengono aggiunte e rimosse spesso, quando le chiavi non sono stringhe, o quando ti serve il numero di voci tramite size. Usa un Record per un insieme fisso di nomi, per gli oggetti di configurazione e per tutto ciò che passi a JSON.stringify.
Perché TypeScript dice che manca una proprietà nel mio Record?
Perché il tipo delle chiavi è una union e l'oggetto ne omette un membro. tsc segnala, ad esempio, Property 'about' is missing in type '{ home: string; }'. Aggiungi la chiave, o racchiudi il tipo in Partial se ometterla è lecito.
Record esiste a runtime?
No. È solo un tipo e sparisce quando il codice viene compilato. L'oggetto che crei è un normale oggetto JavaScript, quindi il compilatore non può impedire che una risposta del server abbia chiavi in più o mancanti.
Quale versione di TypeScript ha introdotto Record?
Record è arrivato in TypeScript 2.1, insieme a Partial, Readonly e Pick, quindi qualsiasi compilatore attuale lo include.
Come è costruito Record
Record è un mapped type. Scorre ogni membro del tipo delle chiavi e assegna a ciascuno lo stesso tipo di valore, ed è per questo che Record<"a" | "b", number> si espande in un tipo oggetto con due proprietà number obbligatorie.
Essendo solo un tipo, puoi passargli qualsiasi cosa possa essere una chiave di proprietà: string literal, number, string, symbol o una union di questi. Un tipo di chiave costruito da un altro tipo, come keyof User, si aggiorna da solo quando User cambia.
Chiavi chiuse contro chiavi aperte
Il valore di Record sta nella forma chiusa. Una tabella di lookup di nomi di route, etichette di stato o colori del tema tipizzata con una union di letterali rompe la build il giorno in cui qualcuno aggiunge un nuovo stato senza etichetta, che è esattamente il momento in cui vuoi saperlo.
La forma aperta, Record<string, T>, descrive un dizionario. Non dice nulla su quali chiavi esistano, quindi leggere una chiave restituisce T anche quando la chiave è assente. Abbinala a noUncheckedIndexedAccess o a una Map quando questa lacuna conta.
Record, index signature o Map
Scegli Record con chiavi letterali per lookup fissi, Record<string, T> o una index signature per dizionari in stile JSON, e Map per collezioni che cambiano mentre il programma gira. La guida a Map di TypeScript su questo sito approfondisce l'ultimo caso.
Gli schemi che userai di più
Chiavi da un array as const
L'array è l'unica fonte di verità. Aggiungici uno stato e il compilatore segnala la tabella delle etichette finché non aggiungi anche l'etichetta.
Un flag per ogni campo di un altro tipo
keyof trasforma un tipo esistente nella union delle chiavi, così l'oggetto dello stato touched di un form elenca sempre gli stessi campi del form.
Un dizionario aperto, letto in sicurezza
Con noUncheckedIndexedAccess attivo, una lettura con chiave calcolata è number | undefined, quindi il valore di riserva è obbligatorio invece di essere dimenticato.
Generatore di tipi Record
Chiavi, separate da virgole
Tipo di valore
Le chiavi sono facoltative (racchiudi in Partial)
Il tipo
In cosa si espande
Un oggetto iniziale
Digita almeno una chiave. Le chiavi devono iniziare con una lettera, _ o $.