Il sovraccarico di funzioni consente di creare una funzione con diverse varianti di parametri accettati e di valore restituito. In altri linguaggi, come C# o Java, è possibile descrivere più funzioni con lo stesso nome ma con diversi tipi o quantità di argomenti. TypeScript approssima questo meccanismo tramite il sovraccarico delle firme a livello di tipo, ma il corpo della funzione è sempre uno.
La situazione è questa: in JavaScript non c'è supporto nativo per il sovraccarico per tipo o quantità di parametri. Con l'arrivo di TypeScript, il sovraccarico viene emulato tramite la dichiarazione di più firme di funzione di seguito e una singola implementazione, all'interno della quale si distingue manualmente il tipo con cui si sta attualmente lavorando.
Il problema sorge se non si tiene conto della corrispondenza con le firme dichiarate: i parametri all'interno del corpo della funzione riceveranno il tipo più generale (unione di tutti i tipi di parametri) e il programmatore dovrà effettuare controlli e type guards.
Soluzione: Tipizzare rigorosamente i sovraccarichi nelle firme esplicite, lavorare correttamente con i tipi di unione e type guards, documentare correttamente il comportamento.
Esempio di codice:
function format(value: string): string; function format(value: number, locale: string): string; function format(value: any, locale?: string): string { if (typeof value === 'number') { return value.toLocaleString(locale); } return value.trim(); } format(' hello '); // 'hello' format(123456, 'ru-RU'); // '123 456'
Caratteristiche chiave:
È possibile dichiarare più funzioni con lo stesso nome e corpi diversi, come in C#?
No. In TypeScript (e in JavaScript) esiste effettivamente solo una funzione con quel nome. I sovraccarichi funzionano solo a livello di tipi per il compilatore, ma esiste solo un corpo di funzione.
Cosa succede se non si implementa la firma con i parametri più generali dopo le firme sovraccaricate?
TypeScript genererà un errore di compilazione. Deve sempre esserci una funzione di implementazione i cui parametri coprono tutte le possibili varianti di sovraccarico.
function foo(a: string): string; function foo(a: number): number; // nessun corpo — errore
Posso utilizzare proprietà specifiche per una specifica firma all'interno del corpo?
No, solo dopo un controllo del tipo (type guard) o un cast di tipo. Altrimenti TypeScript non consentirà di utilizzare queste proprietà direttamente, poiché non è noto quale firma viene attualmente chiamata.
function bar(x: string): number; function bar(x: number): number; function bar(x: string | number): number { if (typeof x === 'string') return x.length; return x * 2; }
Hanno dimenticato di aggiungere la firma di implementazione universale:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; // nessuna implementazione — il compilatore si lamenta
Pro:
Contro:
Implementano il sovraccarico secondo lo standard:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; function sum(a: any, b: any): any { return typeof a === 'string' && typeof b === 'string' ? a + b : a + b; }
Pro:
Contro: