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)