ProgrammazioneSviluppatore Fullstack

Come funziona l'operatore keyof in TypeScript, a cosa serve e come influisce sulla progettazione di funzioni e API sicure?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

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:

  • Consente di dichiarare tipi "chiave" che dipendono dalla struttura dell'oggetto.
  • Rende le funzioni di tipo get/set delle proprietà il più sicure possibile dal punto di vista dei tipi: esclusi errori di battitura e chiavi non esistenti.
  • Funziona anche con proprietà simboliche (symbol), a partire da TypeScript 2.7 e versioni successive.

Domande trabocchetto.

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"

Errori tipici e anti-pattern

  • Utilizzare stringhe costanti per le chiavi invece di keyof — perdita di tipizzazione.
  • Credere che keyof per union restituisca unione, invece di intersezione.
  • Aspettarsi che keyof consideri solo chiavi esplicitamente dichiarate, ma non quelle ereditate.

Esempio dalla vita reale

Caso negativo

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:

  • Codice universale.

Svantaggi:

  • Nessun controllo in fase di compilazione, possibili errori durante il refactoring, vulnerabilità agli errori di battitura.

Caso positivo

Usano generics: getProperty<T, K extends keyof T>(), il tipo key è rigorosamente limitato alle chiavi della struttura.

Vantaggi:

  • Assoluta sicurezza di tipo, l'errore di battitura o l'errore nella chiave è impossibile.

Svantaggi:

  • Codice leggermente più complesso, i generics non sono sempre chiari ai principianti.