Storia della domanda
TypeScript è stato progettato sin dall'inizio per una tipizzazione rigorosa degli oggetti e per scrivere codice JavaScript più prevedibile. Uno degli strumenti per garantire la sicurezza nell'accesso alle proprietà degli oggetti è l'operatore keyof, introdotto in TypeScript 2.1. Esso consente di creare tipi che rappresentano un insieme di chiavi stringa (e simboliche) disponibili nel tipo dichiarato dell'oggetto.
Problema
In JavaScript puro, le proprietà di un oggetto possono essere richieste con qualsiasi stringa, e se si commette un errore, si otterrà undefined o un errore che sarà scoperto solo durante l'esecuzione. Senza una tipizzazione rigorosa è facile commettere errori di battitura o dimenticare di aggiornare la stringa della chiave durante il refactoring. Inoltre, spesso è necessario costruire una funzione che accetti solo chiavi corrette di un determinato oggetto o tipo.
Soluzione
L'operatore keyof crea un tipo unione di tutte le chiavi del tipo. Con esso è possibile limitare le chiavi consentite, elevare la sicurezza dell'API (ad esempio, per funzioni getter/setter) e creare tipi utilitari generici.
Esempio di codice:
type User = { name: string; age: number; active: boolean }; type UserKey = keyof User; // "name" | "age" | "active" function getProp<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } const user: User = { name: 'Tom', age: 33, active: true }; const age = getProp(user, 'age'); // età di tipo number
Caratteristiche chiave:
Cosa restituisce keyof su un array e si possono ottenere indici?
keyof per un array restituisce i tipi delle chiavi dell'oggetto, di cui l'array è effettivamente un esempio in JS. Di solito si tratta di stringhe di indici e proprietà speciali dell'array.
Esempio di codice:
type A = keyof number[]; // "length" | "toString" | "pop" | ... | number
Può keyof restituire chiavi di union-types?
Sì, keyof da un tipo unione restituisce l'intersezione delle chiavi di entrambi gli oggetti, non la loro unione.
Esempio di codice:
type A = {a: string, b: number } type B = {b: number, c: boolean } type C = keyof (A | B); // "b"
Cosa succede se una proprietà dell'oggetto è opzionale? keyof supporta "?"?
Sì, le proprietà opzionali rientrano nel tipo risultante delle chiavi, ma ciò non significa che la proprietà sia necessariamente presente nell'oggetto a runtime.
Esempio di codice:
type D = { a: string; b?: number }; type DK = keyof D; // "a" | "b"
Scrivono una funzione getProperty(obj, key) con chiave di tipo stringa, la chiamano con una chiave inesistente — l'errore appare solo durante l'esecuzione.
Vantaggi:
Svantaggi:
Usano generics: getProperty<T, K extends keyof T>(), il tipo key è rigorosamente limitato alle chiavi della struttura.
Vantaggi:
Svantaggi: