TypeScript Generics is a tool which provides a way to create reusable components. It creates a component that can work with a variety of data types rather than a single data type. It allows users to consume these components and use their own types. Generics ensures that the program is flexible as well as scalable in the long term.
Generics provides type safety without compromising the performance, or productivity. TypeScript uses generics with the type variable which denotes types. The type of generic functions is just like non-generic functions, with the type parameters listed first, similarly to function declarations.
In generics, we need to write a type parameter between the open (<) and close (>) brackets, which makes it strongly typed collections. Generics use a special kind of type variable <T> that denotes types. The generics collections contain only similar types of objects.
In TypeScript, we can create generic classes, generic functions, generic methods, and generic interfaces. TypeScript Generics is almost similar to C# and Java generics.
The below example helps us to understand the generics clearly.
Advantage of Generics
There are mainly three advantages of generics. They are as follows:
Why need Generics?
We can understand the need for generics by using the following example.
In the above example, the getItems() function accepts an array which is of type any. The getItems() function creates a new array of type any, concatenates items to it and returns this new array. Since we have used any data type, we can pass any type of items to the function. But, this may not be the correct way to add items. We have to add numbers to number array and the strings to the string array, but we do not want to add numbers to the string array or vice-versa.
To solve this, TypeScript introduced generics. In generics, the type variable only accepts the particular type that the user provides at declaration time. It is also preserving the type checking information.
So, we can write the above function in generic function as below.
In the above example, the type variable T specifies the function in the angle brackets getItems<T>. This variable also specifies the type of the arguments and the return value. It ensures that data type specified at the time of a function call will also be the data type of the arguments and the return value.
The generic function getItems() accepts the numbers array and the strings array. When we call the function getItems<number>([10, 20, 30]), then it will replace T with the number. So, the type of the arguments and the return value will be number array. Similarly, for function getItems<string>(["Hello", "JavaTpoint"]), the arguments type and the return value will be string array. Now, if we try to add a string in arrNumber or a number in arrString array, the compiler will show an error. Thus, it preserves the type checking advantage.
In TypeScript, we can also call a generic function without specifying the type variable. The TypeScript compiler will set the value of T on the function based on the data type of argument values.
In TypeScript Generics, we can define multi-type variables with a different name. We can understand it with the following example.
Generic with non-generic Type
We can also use generic types with other non-generic types.
TypeScript also supports generic classes. The generic type parameter is specified in angle brackets (<>) following the name of the class. A generic class can have generic fields or methods.
The generic type can also be used with the interface. We can understand the generic interface with the following example.
Generics Interface as Function Type
We can also use generics interface as function types. The following example can understand it.
As we know, the TypeScript Generics Types allows working with any and all data type. However, we can restrict it to certain types by using constraints. In the following example, we will create an interface that has a single .length property. We will use this interface, and the "extends" keyword to denote our constraint.
Length: 10 Length: undefined
Generic Constraints with class
A more advanced example of Generic constraints relationships between the constructor function and the instance side of class types is given below.