Generics in TypeScript

Generics in TypeScript allows us to write a method, function, interface, type alias, or class in such a way that it will allow us to pass in a range of data types. This helps us in re-using the code. In this tutorial let us learn how to use generics in TypeScript using examples.

Generics in TypeScript

Consider the following functions. Both print whatever is passed to them to the console and then return it to the caller.

Both printANumber and printAString are similar functions but only differ in the parameter and return data type. The printANumber function accepts only a number and throws a compiler error if we try to pass any other data type.

The above code is not an efficient way to create functions. The better way is to create a single function in such a way that it can accept any data type but still stays type-safe.

One of the options is to use any as the data type. But that would mean opting out of type checking and defeats the very purpose of using TypeScript.

This is where generics come into the picture. They allow us to create a function, class, or interface using a Generic data type and let us specify the actual data type where we invoke the function or instantiate the class.

Creating the Generic Method

We create a generic method using the syntax

In the above syntax, T is a placeholder for the data type. We enclose it in an angle bracket right after the function name. T is also known as a Type variable, Type parameter, or generic parameter.  We substitute T with the actual data type while we invoke the function.

The following is an example of the Generic Method. Here arg is of type T and also the return type is T.

Generics in TypeScript

We specify the type of T when we invoke the function. For example, we invoke the print function using the syntax print<number>. Here the type of T is a number, which also implies that the return value is also a number.

We can easily pass a string instead of a number. Typescript knows that you are passing a string hence it validates the function assuming the parameter is a string and also treats the return type as string.

Generics in TypeScript

You can also invoke the function without specifying the data type in the angle bracket. In such cases, TypeScript infers the type (Type inference) from the data type of the Parameter.

In the following example, we try to assign the return value of print(10) to a string variable. This statement causes an error because the return type is a number because we have passed a number as a parameter to the function.

We can pass a value of any data type to a generic function. In this example, we pass a boolean and a Typescript object to the print function.

We named our generic type variable T. It is just a convention, you can use any valid identifier in its place. The following example uses xy instead of T.

The return type need not be a generic type.

Even the argument need not be of generic type.

We can also use generic type T to create a local variable. In the following example, the local variable a is of type T.

You can also use multiple generic types. Each generic parameter is separated by a comma inside the angle bracket.

Generics Example

The following is one of the real use cases for the generic function. The reverseArray reverses any array passed on to it. The T[] indicates the array of type T. While invoking you can pass an array of strings, numbers, objects, etc.

Generics Vs Union Types

Union Types can also be used instead of the Typescript Generics. But there are a few differences.

While using union types, we must know all the types upfront. In the following code, we use the union type of number & string. We cannot invoke the print function with any other type other than number or string. For example, if we pass a boolean, it will result in a compiler error. If we use generics then we can pass any data type.

If the return type changes according to the input types, then we need to return the union type from the function. In the above example, the return type is also a union type of number and string. To capture the return value, we need a create a variable of union type or type cast it

The generic functions can return the generic type.

Generics Vs Function Overloading

Function overloading or method overloading is another way to handle multiple types.

In function overloading, you need to know all the possible types of the parameter and their return types. But unlike union types, the return type need not be type cast, or no need to use a union type.

We can also return different return types than the parameter type. For Example, the Parameter type can be a number, and the return type could be a string, etc. We cannot do that using the generic types.

When to Use Generic Types

Use generics when you

  1. Do not know all the possible types
  2. The return type is a direct mapping 

Reference

  1. Generics
  2. Generics Vs Function Overloading Vs Union Types

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top