Storia della domanda
Con lo sviluppo di TypeScript è emersa la necessità di estrarre automaticamente il tipo di valore di ritorno da una funzione, specialmente per grandi progetti con molte funzioni interconnesse. Per questo è stato introdotto il tipo utilitario ReturnType<T>, che è presente nella libreria standard a partire dalla versione TypeScript 2.8.
Problema
Nei grandi e complessi progetti, può essere difficile mantenere la coerenza dei tipi: se si specifica manualmente il tipo di valore di ritorno di ogni funzione e si modificano le firme, è facile ottenere discrepanze quando le firme e le implementazioni non coincidono. Inoltre, se la funzione restituisce una struttura complessa, non è sempre facile sincronizzare manualmente la descrizione del tipo di ritorno in tutti i punti di utilizzo.
Soluzione
Il tipo utilitario ReturnType<T> estrae automaticamente il tipo di ritorno delle funzioni e può essere utilizzato per tipizzare il risultato della chiamata di funzione in qualsiasi parte del codice. Questo riduce il numero di operazioni manuali per la manutenzione dell'infrastruttura dei tipi e minimizza gli errori legati a discrepanze tra il tipo descritto e quello effettivo del valore di ritorno.
Esempio di codice:
function createUser(name: string, age: number) { return { name, age, created: new Date() }; } type User = ReturnType<typeof createUser>; // User: { name: string; age: number; created: Date; }
Caratteristiche chiave:
È possibile utilizzare ReturnType con i metodi delle classi?
Sì, ma è importante tenere a mente il contesto: se il metodo è una proprietà dell'oggetto con una funzione, utilizzare ReturnType<obj['metodo']>.
Esempio di codice:
class MyClass { foo(x: number) { return x * 2; } } type FooReturn = ReturnType<MyClass['foo']>; // Errore di tipo! // Bisogna farlo così: type FooReturn = ReturnType<(x: number) => number>; // number // Oppure estrarre il metodo come funzione: const obj = new MyClass(); type FooReturn2 = ReturnType<typeof obj.foo>;
Cosa restituisce ReturnType per funzioni con void/never?
Per una funzione con tipo dichiarato void, ReturnType restituirà void. Per never - never.
Esempio di codice:
function doNothing(): void {} type Result = ReturnType<typeof doNothing>; // void
ReturnType funziona con le sovraccariche delle funzioni?
No, ReturnType estrae il tipo di ritorno della "implementazione" e non di tutte le sovraccariche. Se ci sono più sovraccariche, viene preso il tipo descritto dall'implementazione.
Esempio di codice:
function func(x: number): number; function func(x: string): string; function func(x: any): any { return x } type RT = ReturnType<typeof func>; // any
In un progetto viene dichiarato un tipo manuale per l'oggetto restituito dalla funzione. La funzione cambia - il tipo non viene aggiornato, le chiamate falliscono a runtime.
Pro:
Contro:
Passano a ReturnType ovunque venga utilizzato il valore restituito dalla funzione. In caso di modifiche, il tipo è sempre aggiornato.
Pro:
Contro: