Function overloading allows you to create a single function with different variants of accepted parameters and return values. In other languages, like C# or Java, you can declare multiple functions with the same name but with different types or numbers of arguments. TypeScript brings this mechanism closer through signature overloading at the type level, but the function body is always one.
The background of the issue is that JavaScript has no native support for type or parameter count overloading. With the emergence of TypeScript, overloading is emulated through declaring several function signatures consecutively and having a single implementation, within which you manually distinguish the type you are currently working with.
The problem arises if the compliance with declared signatures is not monitored: inside the function body, TypeScript assigns the most general type (the union of all parameter types) to the parameters, and the programmer has to perform checks and type guards.
Solution: Strictly type overloads in explicit signatures, work correctly with union types and type guards, and properly document behavior.
Example 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'
Key features:
Can you declare multiple functions with the same name and different bodies, like in C#?
No. In TypeScript (and JavaScript), there is effectively only one function with that name. Overloads work only at the type level for the compiler, but there is only one function body.
What will happen if you don't implement a signature with the most general parameters after the overloaded signatures?
TypeScript will throw a compilation error. There should always be one implementation function whose parameters cover all possible overload variants.
function foo(a: string): string; function foo(a: number): number; // no body — error
Can I use properties specific to one specific signature inside the body?
No, only after a type check (type guard) or type assertion. Otherwise, TypeScript will not allow you to use these properties directly, as it is not known which signature the call is currently following.
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; }
Forgot to add the universal signature-implementation:
function sum(a: string, b: string): string; function sum(a: number, b: number): number; // no implementation — the compiler complains
Pros:
Cons:
Implementing overloading according to the 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; }
Pros:
Cons: