Functie-overloading maakt het mogelijk om één functie te creëren met verschillende varianten van parameters en retourwaarden. In andere talen, zoals C# of Java, kan men meerdere functies met dezelfde naam beschrijven, maar met verschillende types of aantallen argumenten. TypeScript benadert dit mechanisme via overload-handtekeningen op type-niveau, maar de functie-body blijft altijd één.
De kwestie is dat er in JavaScript geen native ondersteuning is voor overloads op basis van type of aantal parameters. Met de komst van TypeScript wordt overloaden geëmimeerd door meerdere handtekeningen van de functie achtereenvolgens te declareren en één enkele implementatie, waarin handmatig wordt onderscheiden met welk type momenteel wordt gewerkt.
Het probleem ontstaat als men niet toeziet op de overeenstemming met de aangegeven handtekeningen: TypeScript kent de meest algemene type (de unie van alle parameter-types) toe aan de parameters binnen de functie-body, en de programmeur moet checks en type guards uitvoeren.
Oplossing: Strikt de overloads typiseren in duidelijke handtekeningen, goed werken met union types en type guards, en het gedrag correct documenteren.
Voorbeeld code:
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'
Belangrijkste kenmerken:
Is het mogelijk om meerdere functies met dezelfde naam en verschillende lichamen te declareren, zoals in C#?
Nee. In TypeScript (en JavaScript) bestaat er feitelijk slechts één functie met deze naam. Overloads werken alleen op typniveau voor de compiler, maar er is maar één functie-body.
Wat gebeurt er als je de handtekening met de meest algemene parameters niet implementeert na de overload-handtekeningen?
TypeScript geeft een compileerfout. Er moet altijd één implementatiefunctie zijn waarvan de parameters alle mogelijke overload-varianten dekken.
function foo(a: string): string; function foo(a: number): number; // geen body — fout
Kan ik binnen de body eigenschappen gebruiken die specifiek zijn voor één specifieke handtekening?
Nee, alleen na type-check (type guard) of type casting. Anders zal TypeScript het niet toestaan om deze eigenschappen rechtstreeks te gebruiken, omdat het niet bekend is op welke handtekening de aanroep momenteel is gebaseerd.
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; }
Vergeten om een algemene implementatie-handtekening toe te voegen:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; // geen implementatie — de compiler klaagt
Voordelen:
Nadelen:
Overload impleteren volgens de norm:
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; }
Voordelen:
Nadelen: