Generics in TypeScript - Learn TypeScript Generics In Depth

Generics is an important feature of TypeScript that allows developers to write flexible and reusable code. With generics, you can write functions and classes that work with a variety of data types, without having to repeat code for each specific type.

In this article, we will introduce the concept of generics and discuss how they can be used to create generic functions and classes. We will also cover constraints, which are used to limit the types that can be used with a generic function or class.

What Generics can do in TypeScript

Generics allow us to define a function or class that can work with any data type. This is useful because it makes our code more flexible and reusable.
Here’s an example of a generic function:

function identity<T>(arg: T): T {
  return arg;
}

let output = identity<string>("hello");
console.log(output); // hello

In this example,

  1. we define a function called identity that takes a generic type parameter T.
  2. The function takes an argument of type T and returns the same value.
  3. We then call the function with a string argument and assign the result to a variable called output.
  4. Finally, we log the value of output to the console.

Generic Functions

Generic functions are functions that can work with any data type. They allow you to write a single function that can handle a variety of data types, without having to duplicate code for each type.
Here’s an example of a generic function that finds the first element of an array:

function first<T>(arr: T[]): T {
  return arr[0];
}

let arr1 = [1, 2, 3];
let arr2 = ["a", "b", "c"];
console.log(first(arr1)); // 1
console.log(first(arr2)); // a

In this example, we define a function called first that takes a generic type parameter T and an array of type T. The function returns the first element of the array. We then call the function with two different arrays, one of type number and one of type string.

Generic Classes

Generic classes are classes that can work with any data type. They allow you to define a class that can handle a variety of data types, without having to duplicate code for each type.
Here’s an example of a generic class that stores a list of items:

class List<T> {
  private items: T[] = [];

  addItem(item: T): void {
    this.items.push(item);
  }

  getItem(index: number): T {
    return this.items[index];
  }
}

let list = new List<number>();
list.addItem(1);
list.addItem(2);
console.log(list.getItem(0)); // 1
console.log(list.getItem(1)); // 2

In this example, we define a class called List that takes a generic type parameter T. The class has two methods, addItem and getItem, that allow you to add items to the list and retrieve them by index.

We then create an instance of the List class with a type parameter of number, and add two items to the list. Finally, we retrieve the items by index and log their values to the console.

Constraints

Constraints are used to limit the types that can be used with a generic function or class. They allow you to define a set of rules that a type parameter must follow in order to be used with the function or class.
Here’s an example of a generic function with a constraint:

interface Lengthwise {
  length: number;
}

function getLength<T extends Lengthwise>(arg: T): number {
  return arg.length;
}

console.log(getLength("hello"));
console.log(getLength([1, 2, 3]));

In this example, We define an interface called Lengthwise that has a single property length of type number. We then define a generic function called getLength that takes a type parameter T which extends the Lengthwise interface. The function returns the length property of the argument. We then call the function with a string and an array, both of which have a length property.

More Examples of Generics in TypeScript - https://www.typescriptlang.org/docs/handbook/2/generics.html

Conclusion

In conclusion, generics are a powerful feature of TypeScript that allow you to write flexible and reusable code. They enable you to define functions and classes that can work with a variety of data types, without having to repeat code for each specific type. By using generics, you can make your code more efficient and maintainable, while also reducing the chances of bugs and errors.

In this article, we have covered the basics of generics, including generic functions and classes, as well as constraints. We hope this article has provided you with a good understanding of what generics are and how they can be used in your TypeScript projects.

Previous
Interfaces in TypeScript - Learn TypeScript Interface in Depth
Next
Modules in TypeScript - Modules in depth in TypeScript