How to Use TypeScript Generics with Practical Examples
Learn how to use TypeScript generics with simple, practical examples. Understand what generics are, how to write them, and common mistakes to avoid, perfect for beginners.
If you are starting with TypeScript and want to write more flexible and reusable code, understanding generics is essential. Generics allow you to write components or functions that can work with different types, not just one. This tutorial will guide you through what TypeScript generics are, how to use them step-by-step, and show practical code examples. Along the way, you will also see related concepts like type inference and function overloading, which often come up when working with generics.
So, what exactly are generics? In TypeScript, generics are a way to create components or functions that can operate on multiple types, with the specific type being decided when the function or class is used. Instead of writing repetitive functions for different types, generics provide one set of logic that adapts to the type provided. This is especially helpful in scenarios like working with arrays, utility functions, or data structures where the element or data type can vary. Generics often work alongside types and interfaces to keep your code both safe and flexible.
function identity<T>(arg: T): T {
return arg;
}
const numberResult = identity(42); // Type is number
const stringResult = identity('hello'); // Type is string
// Generic with an array type
function getFirstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const first = getFirstElement(['apple', 'banana']); // Type is string
const firstNumber = getFirstElement([10, 20, 30]); // Type is numberTo use generics properly, declare a generic type parameter inside angle brackets <> after the function or class name, commonly named T or another letter that reflects the type role. When you call the generic function, TypeScript usually infers the type automatically based on the argument you passed, so you don’t always have to specify the type manually. It’s also important to constrain generics when you want to limit the kinds of types allowed. You can do this with extends to specify that the generic type must have certain properties or belong to a certain type hierarchy. This technique ties in well with interfaces and type aliases.
A common mistake when using generics is overcomplicating your type parameters or ignoring type constraints, which can lead to unexpected errors or loss of type safety. Also, forgetting that generics should be consistent throughout your function signature, meaning if you use the same generic multiple places, it should represent the same type. Another pitfall is confusing generics with any type – generics still keep type information, while any disables checking. Lastly, avoid naming generics with vague letters when working on bigger codebases for better readability.
In summary, TypeScript generics are a powerful feature for creating reusable and type-safe code components. They let you write functions and classes that can work with any data type, reducing duplication and improving maintainability. By understanding the basics, how to declare generics, and common best practices, you can start leveraging them in your projects effectively. As you continue to explore generics, keep in mind how they relate to other TypeScript features like type inference, interfaces, and constraints to fully unlock their potential.