DEV Community

HidetoshiYanagisawa
HidetoshiYanagisawa

Posted on

Must-read for TypeScript Beginners! Deepen your Understanding of Generics

Hello! Today we're going to explain an important concept in TypeScript: Generics. Generics are a powerful tool for solving type issues, enhancing code reusability and flexibility while maintaining type safety.

1. What are Generics?

Generics are part of the type system and a tool to provide flexibility to classes and functions. By using generics, you can abstract and reuse code while maintaining type information (i.e., what kind of data is passed to the code).

For example, consider the following generic function.

function identity<T>(arg: T): T {
    return arg;
}
Enter fullscreen mode Exit fullscreen mode

This function can be called by specifying a type.

let output = identity<string>("myString");
console.log(output);  // "myString"
Enter fullscreen mode Exit fullscreen mode

Also, you can use type inference to automatically infer the type from the argument.

let output = identity("myString");
console.log(output);  // "myString"
Enter fullscreen mode Exit fullscreen mode

2. The Advantages of Generics

The advantages of generics lie in maintaining type safety, code reusability, and self-documentation.

Type Safety

Using generics allows you to abstract code without limiting the types that functions or classes operate on, maintaining type safety at compile time.

For example, the following generic function getArrayItems takes an array of any type as an argument and returns the array as it is. This function can be used with arrays of any type, such as number arrays, string arrays, object arrays, etc.

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

let numArray = getArrayItems<number>([1, 2, 3, 4]);  // number[]
let strArray = getArrayItems<string>(['a', 'b', 'c']);  // string[]
let objArray = getArrayItems<{ id: number }>([{ id: 1 }, { id: 2 }]);  // { id: number }[]
Enter fullscreen mode Exit fullscreen mode

Code Reusability

Using generics allows you to design functions or classes without relying on specific types, enabling the creation of general code that operates with various types.

For example, the following GenericNumber class allows you to create both a version that operates with number type and a version that operates with string type from the same code.

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myNumber = new GenericNumber<number>();
myNumber.zeroValue = 0;
myNumber.add = function(x, y) { return x + y; };

let myString = new GenericNumber<string>();
myString.zeroValue = "";
myString.add = function(x, y) { return x + y; };
Enter fullscreen mode Exit fullscreen mode

Self-Documentation

Generics improve code readability by showing what types functions or classes operate with, making it easier for other developers to understand the code.

3. Generics vs Any

The difference between any type and generics lies in whether they maintain type safety. Using any type might sacrifice type safety. On the other hand, using generics can enhance the reusability and flexibility of the code while maintaining type safety.

let myVariable: any = 'Hello';
myVariable = 10;  // no error, but potentially unsafe!

function identity<T>(arg: T): T {
    return arg;
}
let output = identity<string>("myString");  // output is of type string
Enter fullscreen mode Exit fullscreen mode

As seen above, generics are a powerful tool for enhancing code flexibility and reusability and maintaining type safety. In general, it is recommended to use generics as much as possible to maintain type safety.


That's all for the explanation about TypeScript's generics. I hope this article will help you deepen your understanding of generics in TypeScript. For more detailed information, please refer to the official documentation. Happy Coding!

Top comments (0)