Section 6.3 of the TypeScript language spec talks about function overloading and gives concrete examples on how to implement this. However if I try something like this:
export class LayerFactory { constructor (public styleFactory: Symbology.StyleFactory) { } createFeatureLayer (userContext : Model.UserContext, mapWrapperObj : MapWrapperBase) : any { throw "not implemented"; } createFeatureLayer(layerName : string, style : any) : any { throw "not implemented"; } } I get a compiler error indicating duplicate identifier even though function parameters are of different types. Even if I add an additional parameter to the second createFeatureLayer function, I still get a compiler error. Ideas, please.
16 Answers
When you overload in TypeScript, you only have one implementation with multiple signatures.
class Foo { myMethod(a: string); myMethod(a: number); myMethod(a: number, b: string); myMethod(a: any, b?: string) { alert(a.toString()); } } Only the three overloads are recognized by TypeScript as possible signatures for a method call, not the actual implementation.
In your case, I would personally use two methods with different names as there isn't enough commonality in the parameters, which makes it likely the method body will need to have lots of "ifs" to decide what to do.
TypeScript 1.4
As of TypeScript 1.4, you can typically remove the need for an overload using a union type. The above example can be better expressed using:
myMethod(a: string | number, b?: string) { alert(a.toString()); } The type of a is "either string or number".
This may be because, when both functions are compiled to JavaScript, their signature is totally identical. As JavaScript doesn't have types, we end up creating two functions taking same number of arguments. So, TypeScript restricts us from creating such functions.
TypeScript supports overloading based on number of parameters, but the steps to be followed are a bit different if we compare to OO languages. In answer to another SO question, someone explained it with a nice example: Method overloading?.
Basically, what we are doing is, we are creating just one function and a number of declarations so that TypeScript doesn't give compile errors. When this code is compiled to JavaScript, the concrete function alone will be visible. As a JavaScript function can be called by passing multiple arguments, it just works.
8You can declare an overloaded function by declaring the function as having a type which has multiple invocation signatures:
interface IFoo { bar: { (s: string): number; (n: number): string; } } Then the following:
var foo1: IFoo = ...; var n: number = foo1.bar('baz'); // OK var s: string = foo1.bar(123); // OK var a: number[] = foo1.bar([1,2,3]); // ERROR The actual definition of the function must be singular and perform the appropriate dispatching internally on its arguments.
For example, using a class (which could implement IFoo, but doesn't have to):
class Foo { public bar(s: string): number; public bar(n: number): string; public bar(arg: any): any { if (typeof(arg) === 'number') return arg.toString(); if (typeof(arg) === 'string') return arg.length; } } What's interesting here is that the any form is hidden by the more specifically typed overrides.
var foo2: new Foo(); var n: number = foo2.bar('baz'); // OK var s: string = foo2.bar(123); // OK var a: number[] = foo2.bar([1,2,3]); // ERROR Function overloading in typescript:
According to Wikipedia, (and many programming books) the definition of method/function overloading is the following:
In some programming languages, function overloading or method overloading is the ability to create multiple functions of the same name with different implementations. Calls to an overloaded function will run a specific implementation of that function appropriate to the context of the call, allowing one function call to perform different tasks depending on context.
In typescript we cannot have different implementations of the same function that are called according to the number and type of arguments. This is because when TS is compiled to JS, the functions in JS have the following characteristics:
- JavaScript function definitions do not specify data types for their parameters
- JavaScript functions do not check the number of arguments when called
Therefore, in a strict sense, one could argue that TS function overloading doesn't exists. However, there are things you can do within your TS code that can perfectly mimick function overloading.
Here is an example:
function add(a: number, b: number, c: number): number; function add(a: number, b: number): any; function add(a: string, b: string): any; function add(a: any, b: any, c?: any): any { if (c) { return a + c; } if (typeof a === 'string') { return `a is ${a}, b is ${b}`; } else { return a + b; } } The TS docs call this method overloading, and what we basically did is supplying multiple method signatures (descriptions of possible parameters and types) to the TS compiler. Now TS can figure out if we called our function correctly during compile time and give us an error if we called the function incorrectly.
What is function overloading in general?
Function overloading or method overloading is the ability to create multiple functions of the same name with different implementations (Wikipedia)
What is function overloading in JS?
This feature is not possible in JS - the last defined function is taken in case of multiple declarations:
function foo(a1, a2) { return `${a1}, ${a2}` } function foo(a1) { return `${a1}` } // replaces above `foo` declaration foo(42, "foo") // "42" ... and in TS?
Overloads are a compile-time construct with no impact on the JS runtime:
function foo(s: string): string // overload #1 of foo function foo(s: string, n: number): number // overload #2 of foo function foo(s: string, n?: number): string | number {/* ... */} // foo implementation A duplicate implementation error is triggered, if you use above code (safer than JS). TS chooses the first fitting overload in top-down order, so overloads are sorted from most specific to most broad.
Method overloading in TS: a more complex example
Overloaded class method types can be used in a similar way to function overloading:
class LayerFactory { createFeatureLayer(a1: string, a2: number): string createFeatureLayer(a1: number, a2: boolean, a3: string): number createFeatureLayer(a1: string | number, a2: number | boolean, a3?: string) : number | string { /*... your implementation*/ } } const fact = new LayerFactory() fact.createFeatureLayer("foo", 42) // string fact.createFeatureLayer(3, true, "bar") // number The vastly different overloads are possible, as the function implementation is compatible to all overload signatures - enforced by the compiler.
More infos:
0As a heads up to others, I've oberserved that at least as manifested by TypeScript compiled by WebPack for Angular 2, you quietly get overWRITTEN instead of overLOADED methods.
myComponent { method(): { console.info("no args"); }, method(arg): { console.info("with arg"); } } Calling:
myComponent.method() seems to execute the method with arguments, silently ignoring the no-arg version, with output:
with arg 2