Better Code: Generics in Typescript — Monkey Work, Baboon Chop

The phrase “Monkey Work, Baboon chop” is used in my country and I will decipher what it means at the end of this article. Meanwhile, before we dive into Generic, let’s take a step back to see the headache we avoid by using a strictly typed language.

What is Strongly and Loosely typed language?

According to Wikipedia: Generally, a strongly typed language has stricter typing rules at compile time, which implies that errors and exceptions are more likely to happen during compilation. Dynamically typed languages (where type checking happens at run time) can also be strongly typed. Most of these rules affect variable assignment, return values and function calling.

A weakly typed language has looser typing rules and may produce unpredictable results or may perform implicit type conversion at runtime. A different but related concept is latent typing.

If this doesn’t make so much sense to you, we are in the same boat but let’s take a look at examples in Javascript.

Can you think about the problem with the Lamda function?

  • Javascript v8 engine doesn’t know what ‘a’ and ‘b’ are
  • Javascript v8 engine doesn’t know what the function will return

Now let’s use this function as a client.

Imagine if you are getting a JSON payload from the server and you need to perform computation on it, you can quickly run into unexpected results because Javascript is a loose language.

Let’s write that function in Typescript

Sweet! now if we try to use the same code with the console log above, the interpreter will yell at us, because it is expecting a number and we are passing two parameters of type string in second and third log.

Well, this is good but it is still bad. Hmmm!, we now have control over what our arguments are, there is nothing stopping me from returning a string.

We have decided to add the returned value from addValue which is ‘5’ to 100, the expected output should have been 105 but we got 5100, the reason is because our return value from the addValue is loose hence we can return any data type. To fix that:

The code above forces the arrow function to return a number data-type. Understanding this concept will help us grasp the remaining part of the article.

Why do we need Generic

In Java, generics are mostly used in Collections API to allow the client to specify the data type to be used.

According to Wikipedia, Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.

Let’s take a little example of a Typescript function.

This function takes a number as an argument and then returns a number. Ok, what is the problem with this simple function, can we call this function with a string? No, if we want to call it with a string, we have to create a different version with a string parameter and make it return a string like this:

Ok, what if we want to use an object, array e.t.c This is where Generics programming comes to the rescue. How do we solve this problem with Generics?

What we have done is to basically declare a generic annotation with “<T>” and we replace all our statically typed data types with the generic annotation we have declared. You can see we have been able to decouple our function from any data type and we can call this function with any data type.

This example is not so useful but I hope it drives the concept home. The next example below is a stack data structure.

Looking at the code, you can see that we use generic as the Array data type, Array<number>.

Note: This was what motivated me to write about it.

Let’s try to use the stack as a client

The same problem arises, we can’t create a Stack with a string, array, object e.tc.

To solve this problem with Generics, we have to declare the class as a generic class, just like the Array example.

We have now declared our class with the generic <T> syntax, what that means is that we can declare the type we want to tie this class into.

And then notice that we are returning the same type in the pop and peek methods, in the push method, we are taking the same type as the argument to push.

Let’s use this as a client. We can still use this class as a loose class by using it as a normal javascript class without the strong type feature, Typescript lets us use that with the ‘any’ data-type.

The above example is loose, notice how I pass the number 1 in the first push operation, and then pass the string ‘Wale’ in the second push operation. If we want to be strict (we already saw the benefits in the previous section), we can use the strict Stack in two different ways:

The first way is to specify the data type when instantiating the Stack object as indicated below.

The second way is to make the variable stack which is a reference to the instantiated object to be of type number

Conclusion

Looking at the example code we have, you will notice that we get the interpreter to help us detect errors at runtime. The transpiler yells at us when there is a mismatch in our data-type binding. It is important to state that, typescript is built around javascript, hence loose code will run without any issue but you won’t get away with it when you work with compile languages like Java. The phrase “Monkey Work, Baboon chop”, actually this is a remixed version, the original version is “Monkey dey work, Baboon dey chop” is analogous to a person who does the dirty job in the background and then you get someone else taking credit for the work done; when we write generic code, the developer takes credit for it and none goes to the Typescript that is doing the dirty job under the hood.

Apprentice Developer — Learning to declare variable right

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