Function Overloading

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional TypeScript Masterclass Lessons

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11

Function Overloading

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Basics

Functions can have multiple signatures added to allow various ways they can be invoked. For example:

function reverse(string: string): string;
function reverse(stringArray: string[]): string[];
function reverse(stringOrStringArray: string | string[]) {
if (typeof stringOrStringArray === 'string') {
return stringOrStringArray.split('').reverse().join('');
} else {
return stringOrStringArray.slice().reverse();
}
}

Classes

Class constructors can also be overloaded. For example:

class Point {
constructor(x: number, y: number);
constructor(x: number, y: number, z: number);
constructor(public x: number, public y: number, public z: number = 0) { }
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

Here we have a function called reverse that can be called with a string or a string array. And if it is a string, then it splits the string into its characters, reverses them, and then finally joins them back to return the reversed string. Alternatively, if it is invoked with a string array, it creates a copy of the array using slice and returns the reversed version of that array. So if we invoke this function with the string, hello, we get the reversed string. And similarly, if we invoke it with an array of characters, we get back a reversed array of characters.

00:34

Now we know that if the input is a string, then the output of the function is a string. And if the input is a string array, then the output is a string array. However, as far as the inference engine in TypeScript is concerned, there are two possible ways that the function can return. It can either return a string or it can return a string array. And TypeScript infers the return type of the function to be a string or string array. So if we hover over the first variable, you can see the TypeScript thinks that it might be a string or a string array, and the same is true for the second variable.

01:05

Now the solution to this problem is function overloading. We can declare multiple signatures for any given function before the function body. So we declare a function signature such that it takes an input string and it out outputs a string. And another signature specifying that when it takes a string array, it returns a string array. Now with these two function overloads in place, TypeScript knows that when this function is invoked with a string, it returns a string and infers that correctly for the first function call. Similarly, it correctly infers a string array for the second function call.

01:39

Now function overloading in TypeScript is compile time only. That is these signatures are not a part of the output JavaScript. This is why we are only allowed to have one body for the function, which must handle all the overload cases. For example, here we are using a type of check to determine which code block we want to execute. Additionally, adding overloads shadows the internal function signature. So let's look at another example to demonstrate that. Here we have a function called make date designed to help us make date objects within the function.

02:12

We check if a month and day were passed in. And in that case, we assume that the arguments are the year, the month, and the day. Otherwise we assume that the first argument is a timestamp. That is the time in milliseconds since epoch. So we can create an instance of the date using the make date function, passing in the year 2000, month 10 and day first. Similarly, we can create a date by passing in the time since epoch, and let's just pass in zero to create the date of epoch. Now, if someone were to look at just the function signature, they very well might assume that you should be able

02:46

to pass in just the year in the month. However, when we look at the code, you can see that if day is not passed in, then the second code block will execute. And in that case, the month argument will be completely ignored and The ear argument will actually be thought of as a timestamp in milliseconds. However, with the single function signature that we have right now, we are able to invoke the make date function with two arguments once more. The solution to this problem is to declare function overloads. So we create a function overload where we accept a timestamp of type number and specify that we will return a date.

03:21

And then another function signature where we specify that we will take three arguments, which is year, month, and day, and then return the date. Now, when we declare the overloads, it essentially shadows the internal function signature. And now externally, there are only two possible ways to invoke the function. One with the timestamp and one with year, month, day. So now TypeScript is correctly highlighting the fact that you cannot invoke the make date function with just two arguments, and we can get rid of this incorrect function call. So now you might be wondering why we need

03:54

to have an implementation signature when it is not visible to consumers of our API. Well, the reason is that the implementation signature is there only for the author of the function to declare how they would like to handle all of the possible cases declared by the overloads. This is the only function signature that is visible within the body of the function.

Professional TypeScript Masterclass

Professional TypeScript Masterclass

1.Introduction
free
⏱️ 1:54
2.Setup
free
⏱️ 5:44
3.Primitive Types
free
⏱️ 1:42
4.Instance Types
free
⏱️ 1:52
5.Arrays And Tuples
free
⏱️ 1:38
6.Objects
free
⏱️ 1:33
7.const declarations
free
⏱️ 1:03
8.Function Types
free
⏱️ 1:57
9.Structural Typing
free
⏱️ 2:10
10.Classes in TypeScript
free
⏱️ 1:48
11.Target Compiler Option
free
⏱️ 2:37
12.Generics
⏱️ 3:02
13.Special Types any And unknown
⏱️ 2:00
14.JavaScript to TypeScript
⏱️ 1:32
15.Frontend Projects
⏱️ 3:49
16.Type Assertions
⏱️ 2:15
17.Type Casting
⏱️ 1:16
18.Modules
⏱️ 1:55
19.Type Declarations
⏱️ 4:25
20.Creating NPM packages
⏱️ 3:20
21.Async Await
⏱️ 3:05
22.Running in NodeJS
⏱️ 1:40
23.Lexical this
⏱️ 2:34
24.readonly Modifier
⏱️ 1:59
25.Union Types
⏱️ 2:57
26.Literal Types
⏱️ 2:58
27.Type Narrowing
⏱️ 4:19
28.Discriminated Unions
⏱️ 3:29
29.Class Parameter Properties
⏱️ 1:02
30.Strict Compiler Option
⏱️ 6:18
31.null vs undefined
⏱️ 4:19
32.Intersection Types
⏱️ 2:03
33.Optional Modifier
⏱️ 2:47
34.Non Null Assertion Operator
⏱️ 3:40
35.Interfaces
⏱️ 2:28
36.Interface Declaration Merging
⏱️ 1:01
37.Types vs Interfaces
⏱️ 2:16
38.never Type
⏱️ 3:00
39.implements Keyword
⏱️ 1:25
40.Definite Assignment Assertion
⏱️ 2:31
41.User Defined Type Guards
⏱️ 2:02
42.Assertion Functions
⏱️ 3:42
43.Function Overloading
⏱️ 4:15
44.Call Signatures
⏱️ 2:53
45.Abstract Classes
⏱️ 1:53
46.Index Signatures
⏱️ 3:08
47.Readonly Arrays and Tuples
⏱️ 2:58
48.Double Assertions
⏱️ 2:20
49.const Assertions
⏱️ 3:55
50.this Parameter
⏱️ 2:33
51.Generic Constraints
⏱️ 2:43
52.typeof Type Operator
⏱️ 2:12
53.Lookup Types
⏱️ 3:12
54.keyof Type Operator
⏱️ 3:55
55.Conditional Types
⏱️ 4:39
56.Contitional Types with Unions and never
⏱️ 3:32
57.infer Keyword and `ReturnType<T>`
⏱️ 3:47
58.Mapped Types
⏱️ 2:48
59.Mapped Type Modifiers
⏱️ 3:37
60.Template Literal Type
⏱️ 4:28
61.Partial<T>
⏱️ 1:27
62.Required<T>
⏱️ 1:36
63.Readonly<T>
⏱️ 1:34
64.Record<K, T>
⏱️ 4:05
65.Project References
⏱️ 4:18
66.undefined vs. optional
⏱️ 2:48
67.satisfies Operator
⏱️ 2:42
68.PropertyKey Type
⏱️ 0:57
69.ThisType<T>
⏱️ 4:11
70.Awaited<T>
⏱️ 4:12
71.String Manipulation Types
⏱️ 3:36
72.Mapped Types as Clauses
⏱️ 4:01
73.Union vs Intersection Mental Model
⏱️ 3:36
74.Enums are Bad
⏱️ 8:11