we'll dive into TypeScript generics, exploring what they are, why you should use them, and how to wield their full potential. Let's get started! 🏊♂️
What Are TypeScript Generics?
At its core, TypeScript generics provide a way to create reusable, type-safe components. They allow you to write functions, classes, and interfaces without committing to a specific data type. Instead, you can use placeholders (typically represented by T
, U
, or other descriptive names) that get replaced with actual types when you use the generic component.
function identity<T>(arg: T): T {
return arg;
}
T
is a generic type parameter. When you call identity(42)
, TypeScript infers that T
should be number
. When you call identity("Hello")
, T
becomes string
. Neat, right? 😎
Why Use TypeScript Generics?
Type Safety: Generics ensure that your code is type-safe. They catch type-related errors at compile-time, saving you from runtime headaches.
Reusability: Generics promote code reuse. You can create functions and classes that work with a wide range of types, reducing duplication.
Flexibility: Generics give you the flexibility to work with different data structures without sacrificing type safety. Think arrays, linked lists, trees, or custom data structures.
IDE Support: TypeScript's IDE support is top-notch. With generics, your code editor can provide intelligent suggestions and autocompletions.
How to Use TypeScript Generics
Functions
function reverseArray<T>(arr: T[]): T[] {
return arr.reverse();
}
You can call this function with any array type.
const numbers = [1, 2, 3];
const reversedNumbers = reverseArray(numbers);
const fruits = ["apple", "banana", "cherry"];
const reversedFruits = reverseArray(fruits);
Classes
Generics are not limited to functions. You can use them with classes too. Imagine creating a Stack
class:
class Stack<T> {
private elements: T[] = [];
push(item: T) {
this.elements.push(item);
}
pop(): T | undefined {
return this.elements.pop();
}
}
This Stack
class can work with any data type:
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
const poppedNumber = numberStack.pop();
const stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
const poppedString = stringStack.pop();
Constraints
Sometimes you want to narrow down the types you can use with generics. You can do this using constraints. For example, you might want to create a function that works only with objects that have a length
property.
function getLength<T extends { length: number }>(obj: T): number {
return obj.length;
}
Now, you can't use getLength
with just any type; it must have a length
property.
const array = [1, 2, 3];
getLength(array); // Works
const str = "Hello";
getLength(str); // Works
const num = 42;
getLength(num); // Error: 'length' does not exist on type 'number'
Top comments (0)