My thoughts on types

Felipe Gonçalves Marques
TaqtileBR
Published in
4 min readJul 3, 2018
Photo by Samuel Zeller on Unsplash

My two last posts were focused specifically in Angular. So I decided to write this one to talk about a more general software development concept : Types. But the examples will still be in Typescript. ;)

TL;DR;

Functions and class fields should always be typed. This includes both functions arguments and returns values, also public and private fields.

Introduction

Types allows us to specify what we expect a variable to be. This brings two benefits:

  • Errors are thrown when this expectation is broken:
  • Our code conveys more information about its intent, being easier to understand

But sometimes, typing everything can be really annoying and might not bring enough benefits (Java feelings…).

Lots of modern languages as Python, Ruby and Javascript uses dynamic typing which frees us from having to specify every variable type. Other languages uses static typing with types inference as TypeScript. It allows us to specify types to our variables, but if we don't, it'll try to infere it.

So as we can see, there is a trade-off between using or not type checking. Currently, I have the following opinion about it:

When to use types?

#1 Types should be used whenever we have data coming from outside or going outside of the application

If we are using a library, fetching information from an API through HTTP or answering requests in the server, we should use types.

When we have data coming and going from the application, we have expectation about it. Types help make those expectations clear.

They define what information we expect to receive and what information we will be sending. This allows anyone using the application to understand its interface and, if you have some type of test that checks your expectations, it is easy to find breaking changes.

Lot of companies are using tools as Apollo GraphQL, Apache Thrift, etc, because those tools allow us to keep the API models synchronised through client and server. They align the expectation between the communication models — they also do a lot of other stuff.

Also the Typescript community puts a lot of effort in keeping Types definition for Javascript libraries consistent and working in the DefinitelyTyped repository.

Personally, I think that if we begin using types in those entrypoints of data, will be much easier to keep using types inside the application.

PS: In the clean architecture, every layer frontier is an entrypoint of data, so it should be typed.

#2 Types should always be used whenever we have class fields or functions

Class fields (both private and public) and functions are used distant from its definition (can be a few lines or a few files away). So to guarantee that it is being used correctly, we should use types.

It allows us to catch mistakes at compile-time and convey information about the contract that this artefact defines.

For example, suppose we have the following method to fetch users:

When we use it at some point at our application, we get no information from its signature about the params it expects. We may check its documentation or its implementation — hopping it is simple enough to understand at a glance. But, by lack of attention, we may do a mistake and end up using it like this:

The result will not be as expected and we'll have to check the documentation or the implementation again…

But, if we modify our method to the following:

There will be an warning in compile-time or even in the Text Editor, saving some time and some users from a bad experience.

#3 It is ok to not use types in small scopes with variables that will not be returned or passed away.

If you are implementing a small function and in its implementation you use some variables, it might be ok to not type it. Since this will be restricted to these scopes, we don't face the problem of it being misused somewhere else.

For example, if I have the following code, it is ok to not type the private variables in these scope.

Both the status and the emails variable are implicit defined in the User and UserFilter interface, so it is ok to not type then and let Typescript infere its type.

Conclusion

A good rule of thumb for defining when to use types is: "How far is this going to be used from its definition?".

If it is a more then a few lines from the definition, it should be typed.

There are lot of tools that can be used to enforce typing:

And almost every language has functionalities as generics, partial, enums.

So, remember the old saying: Better (type-)safe than sorry. ;)

--

--