I am reading about function overloads. Essentially what they are is, you are creating let's say 3 functions, with the same name, that are passing 3 different parameters and return types. I am new to TS and I was wondering the following: wouldn't passing a union type and returning a union type be the same? Or is it something completely different?
This is what came up in my head as an example. Would this work or not?
Overload:
function f1(a: string) {
}
function f1(a: number) {
}
Using a union type:
function f1(a: string | number):string | number {
}
Function overloading maps a specific input type to a specific return type. With a union you just know that the return is one of the valid types, but you lose the association between the input and the output. This may or may not be a problem depending on how and where you use the function. But that's the difference.
Here's what it looks like with overloads. The last line of the signature isn't one of the overloads, it describes the types for the implementation. Sometimes you'll see any
, but you can also use the union here.
function overloaded(a: string): string
function overloaded(a: number): number
function overloaded(a: any): any {
return a;
}
The different arguments return the specific type based on the overload that they match.
const oNum: number = overloaded(0);
const oStr: string = overloaded("");
const oBool = overloaded(true); //error
In our union, both input types just return the union, so we've lost the specificity.
function union(a: string | number): string | number {
return a;
}
const uNum: string | number = union(0);
const uStr: string | number = union("");
const uBool = union(true); //error
There is a third option which is typescript generics. This allows us to keep the specificity while accepting infinitely many types. The boolean
example works now. We are telling typescript "look at the type of the argument a
and call that T
". Then we get this type variable T
which we can use in the return type. Here we just returning the same type T
directly, but there is a lot more than you can do with it.
function generic<T>(a: T): T {
return a;
}
const gNum: number = generic(0);
const gStr: string = generic("");
const gBool: boolean = generic(true);