In TypeScript, you can declare an overloaded function by declaring the function with a multiple invocation signatures.
interface Foo { bar: { (s: string): number; (n: number): string; } }
or
interface Foo { bar(s: string): number; bar(n: number): string; }
The type checker of TypeScript works as expected:
var foo1: Foo = ...; var n: number = foo1.bar('hello world'); // OK var s: string = foo1.bar(123); // OK var a: boolean = foo1.bar(false); // ERROR
However, you can’t actually define an overloaded function with multiple function definitions as in C# or Java. The compiler complains about “error TS2393: Duplicate function implementation”. This happens because the signatures of both bar
functions are identical once their types are erased.
class FooClass implements Foo { bar(s: string): number { return s.length; } bar(n: number): string { return n.toString(); } }
is translated to
var FooClass = (function () { function FooClass() { } FooClass.prototype.bar = function (s) { return s.length; }; FooClass.prototype.bar = function (n) { return n.toString(); }; return FooClass; })();
To define an overloaded function in TypeScript, the function must be singular and perform appropriate dispatching internally using type guards.
class FooClass implements Foo { public bar(s: string): number; public bar(n: number): string; public bar(arg: string | number): any { if (typeof arg=== 'number') return arg.toString(); if (typeof arg === 'string') return arg.length; } }
When you declare a variable with FooClass
, you can’t see bar(arg: string | number)
method even though it is declared as public. It is automatically hidden by the more specifically typed overloads.
TypeScript’s function overloads are a bit more flexible than those of C# or Java in that an overloaded function can have different return types. Note that bar(arg: string)
returns number
while bar(arg: number)
returns string
.
Pingback: Thoughts on Intersection Types | Kwang Yul Seo