Generics in TypeScript

Learn via video courses
Topics Covered

Overview

Most object-oriented programming languages have an inbuilt feature similar to generics in typescript which allows those programming languages and TypeScript to create reusable components that can take many types or inferred types.

generics in typescript are a way of creating reusable components like functions, where the return type can be inferred from arguments it receives.

Prerequisites

In order to use generics in typescript, you'll need to have TypeScript installed on your machine and an environment where you can execute TypeScript programs:

  1. Install TypeScript
    • if npm is already installed on your machine:

  2. Install an IDE with debugging support for typescript like Microsoft's VS code.

Introduction

  • Every object-oriented programming language has ways to write components (i.e functions, classes, etc) that are reusable in the code.
    • Here reusable means that the components can work with more than one, even multiple, types.
  • This concept of reusability can be achieved even without the use of generics in typescript, but there are obvious drawbacks to it.
  • any type allows typescript to attain reusability without the use of generics in typescript

Let us understand this by taking an example in the next section.

The Basics of Generics - The Identity Function

Before starting with an example let us understand, what is an Identity function?

An identity function is a function that will return the argument.

An identity function is essential to understand the drawbacks of using any instead of generics in typescript

Now since we are not using generics in typescript, for now, there are two ways to define the identity function:

  1. With a specific type
  1. using any

The biggest drawback to using any over generics in typescript is that the compiler will loose information about the type of argument X when the function returns, this happens because the only information the type that could be returned will be any.

Therefore, generics are used!

Why Generics?

  • generics in typescript provide a way of code reusability where the return type can be inferred from the type of its arguments.
  • generic components can enforce the type that is passed in when the component is used which improves reusability and reduces duplication.

Generics Syntax

  • generics in typescript are implemented using generic types placed between angular brackets: <Type> or <T>
    • <T> is a generic of type T
    • it is a placeholder for a type
  • More than one generic types can be declared in a single definition like <T, C, N>

Working with Generic Type Variables

  • Working with generic type variables concerns correctly using generic type variables in the body of the function.
    • This concern arises from the fact that every type has some in-built functions which might not necessarily work with other types.
      • for example, some types like array have length property that is not present in other primitive types and causes errors when invoked with a generic type

from the above example, it is clear that situations where using a common property for every type can happen anytime, therefore, generic type parameters should be decided carefully when using generics in typescript.

The above example can be rewritten as:

Generic Types like Array<T> can be created based of user's requirements

Generic Types

Generic Types refer to the generic custom types that are created based on the user's requirement

  • The above generic type is an identity generic type which means that this function returns the type that is passed as a type parameter.

someType is of type string because GenericIdentityType returns the type parameter as passed.

Generic Classes & Interfaces

  • while creating generic interfaces or classes in typescript, the type parameter list (i.e list of generic types between angular brackets <>) can be added right after the identifier (interface/class name).

Generic types of generics in typescript can be used to create a call sign for an object literal type which allows us to write generic interfaces:

  • Generic interfaces/classes in typescript become especially helpful when the types of the attribute depend on how the client code is using the class/interface.

Generic Constraints

In the section Working with Generic Type Variables we discussed the concerns with correctly using generic type variables in the body of a function because when using some in-built properties of certain types (like the length property of Array type) on generic types might lead to error. This problem can be solved using generic constraints.

  • Generic constraints contain a function to work with all the types that also have some properties needed that are mentioned beforehand.
    • interface is used to describe the constraint
      • This interface has a list of properties and the primitive type it returns associated with it.
    • now the generic types are extended with this constraint interface using the extends keyword

Now, when calling constrained functions we need to pass in values that have all the required properties mentioned in the interface.

Using Type Parameters in Generic Constraints

  • a type parameter that is constrained by another type parameter can be declared
    • for example, here we want to get the second names of people from an object given the key

Here we have to make sure that we are not requesting a property that does not exist in the object passed to us, therefore the key that we are referencing is constrained, i.e there is a constraint between the two types in the type parameter list.

Using Class Types in Generics

  • using class types in generics relies on using generics with class inheritance to extend other base classes.
    • class types should be referred to by their constructor functions

Conclusion

  • generics in typescript are an old concept in object-oriented programming and similar implementation can be found in many other languages.
  • generics in typescript are a way of creating reusable components like functions, where the return type can be changed based on the parameter.
  • generics in typescript can be applied to functions, interfaces, and custom types (implementations can be found above)
  • generics in typescript improve code reusability and allows us to write flexible code.
  • generics in typescript are implemented in TypeScript using generic types placed between angular brackets: <Type> or <T>