Learning TypeScript — Functions

Photo by Rehan Syed on Unsplash

This is part 3 of the Learning TypeScript series. In part 2, we looked into what interfaces in TypeScript are and how they describe the shape of our objects in JavaScript. In this article, we will be exploring functions in more detail.

Function Typing

TypeScript supports both named and anonymous functions just like in JavaScript. To add types to our functions, we could explicitly add types to our parameters and return values (optional).

Another way we can type check is by defining the type first before referencing that type with our function.

If you have been keeping up with this series, in part 2, we explored how interfaces could be given call signatures to define the types of the parameters and return value as well.

Functions can also be type checked by using generics which allows us to relate the input type to the output type. Generics will be covered in a later article, for now, just note that we can use generics by calling a type parameter in our function signature.

From the code snippet, we have 2 generic types: T and O. These types represent the types for arr1 and arr2 respectively. With generics, we have linked the types for our inputs with our output. Therefore, we can expect the output to have a type of T or O given the union assignment within the array which will be defined by the arguments passed onto the functions. More on union types will be covered in a later article.

Contextual Typing

When assigning a function to a variable, the TypeScript compiler is able to infer the type if defined on only one side of the assignment.

With contextual typing, the amount of code you need to write will be cut down.

Optional and Default Parameters

When it comes to parameters, unlike JavaScript, TypeScript is strict on the number of parameters and their respective types.

We can see that with required parameters, we are constrained to having the exact number of parameters and that each of these parameters must exist.

In order to reduce the strictness of TypeScript on parameters, we can use optional and default parameters. To make a parameter optional, we add a ? at the end of it. We can also assign a default value to a parameter in the case where the argument is not provided or is undefined.

Rest Parameters

If we want to work with multiple parameters as a group or an unknown number of parameters, we would have to use followed by the parameter name. This is known as a rest parameter. For rest parameters, the compiler will treat them as an array and evaluate the types within that array for type correctness.

“this”

Another neat feature in TypeScript is that it is able to catch errors when it comes to this. this can be tricky to deal with at times as it’s reference changes based on context.

From the code snippet above, use strict was defined for consistency. This results in identity() and passedIdentity() to be undefined instead of window for the browser or global for node.

While who.identity() and passedIdentity() was defined within the same class, the context of passedIdentity() was shifted globally when it was assigned to the variable passedIdentity. passedArrowIdentity() retained its this as WhoThis by using the arrow function which binds this to the object.

"this" Parameters in Callbacks

For checking this within callback functions, you can annotate them within your functions.

TypeScript will check the instance of this and ensure that the types are correct. In the case of passedIdentity(), this was typed as WhoThis. However, TypeScript recognized that this has a type of void instead and threw an error. For passedArrowIdentity(), since it was an arrow function, it cannot have a this parameter as the type is already implied to be WhoThis.

Overloads

Since a function can accept different types of arguments and output different return types as well, we can use overloads to encompass those behaviors.

TypeScript will go through each of the overloads and checks to see if the arguments used for the function calls match the overload signatures. Note that guessTypes(guess: any): any is not part of the overloads, therefore there are only three overloads.

Conclusion

In this article, we learn that we can be strict with the number and types of functions parameters and the type of it’s return value.

We can also “widen” the type strictness with optional and default parameters, allowing for different behaviors when calling our functions.

Understanding this is important in type checking our functions, especially for those that get passed around from one context to another.

And finally, with overloads, our functions are able to accept different combinations of input and output types.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Bryan W.

Bryan W.

I have a passion for coding | Salesforce Developer