Generics
Generics is not a new term in today’s programming world. Most of the programming language has this feature. Today, we are going to learn about Generics in TypeScript. It is very easy, and powerful feature of any programming language.
What is Generic?
Like functions, generics are also another kind of function for variable types. Normally, we create functions to reuse it in multiple places of your program. OR you can say, functions are used for any repeated tasks.
Generics also do the same thing, but in a little different manner. Using generics, we make a generalized function for different data types, instead of creating separate functions for each data type. You can define Generic classes, interfaces and functions in TypeScript. These all can work with different data types using the concept of Type Parameters
.
What is Type Parameters?
Type parameter is used to define the data type of any parameters of generic class or interface. Generally, type parameter is denoted by T or
Generic Function
In the above example, you can see, we have created a generic function funcName,
along with type parameter T. We are also mentioning the return type using T in the syntax. We can pass any data type in the function.
Calling the generic function with string type
let output = funcName
(“Hello Adesh”);
Here, we call the function with string type, and get the same type in the return.
Calling the generic function with number type
let output = funcName
(100);
Again, we called the same function, with number data type, and get the same type in the return.
So, in both function calling, our generic function worked well for both type parameters of string
and number
. It didn’t break any code and it is totally type-safe
as well.
Generic Class
Like Generic functions, we can create Generic Classes
using the type parameter T. Our generic class can work with different data type. Let’s create a generic class and pass the string and number data type values. For eg.
Call our generic class by string
Call our generic class by number
Generic Interface
We can create Generic Interface in TypeScript. The following are the examples of generic interface.
Generic Interface as Type
The IExample
is generic type. Here, we are passing two type parameters T & U
. Example1
is passing number and string to generic type. Example2
is passing number and number to generic type.
Generic Interface as Function Type
In the above example, we have created a generic interface IKeyValuePair, which includes the generic method without the method name. We can use any function, which match the signature of our generic method of interface.
We have two functions, NumKeyPairs
& StrKeyPairs
, which has matching signature with our generic method of generic interface. Later, we set the generic types, while creating the variables numKeyValue
& strKeyValue
.
If you look at the above code, we can also generalized these two functions NumKeyPairs
& StrKeyPairs
as well. This generalization of functions will reduce our overall code and make it concise implementation.
Generalized version of above code
As you can see, we have removed functions NumKeyPairs
& StrKeyPairs
, and created a generic function funcKeyValuePairs
. Now, there is no need to create two separate functions. Then, we set the new generalized function funcKeyValuePairs
to both variables numKeyValue
& strKeyValue
.
Generic Interface implementation in Class
We can implement generic interface in a class, same as other non-generic interface.
Here, we have created a class clsKeyValue
, and implements the generic interface IKeyValuePair
. We set the generic type parameters while creating the object of the class. This class will implement the generic method printKeyValue
of generic interface.
Generic Constraints
Sometimes, we don’t want to create our generic classes, functions and interfaces for all data type parameters, or put some specific requirements/constraints. In our below example, we are going to create a function, where the passing parameters much have an Id
property. Let’s see, how can we achieve this using the Generic Constraints.
Here, for function funcKeyValue
, an Id must be required. To achieve this requirement, we have created an interface IdRequired,
and extend our function with this interface. Now, let’s see, what will happen when we pass this parameter in the function.
Above code will show an error message, and alert the undefined value. Because, there is no Id property passed to the function. So, what is the proper way of calling the above function.
let val = funcKeyValue({Id:1, name: ‘Adesh’});
This is the right way of calling our function. This call has an Id property, and our function will work properly. It will not show any error message.
So, we see, how we achieved generic constraints using interfaces.
Summary
In this blog, I we learned about generics, different kind of its implementation with functions, classes and interfaces. We learned about how to avoid writing the duplicate code, and make our program concise and type-safe as well. Generics improves the code reusability and encapsulation.
I hope you enjoyed a lot reading this post.