Mastering TypeScript Generics for High-Performance Code
Learn how to use TypeScript generics to write flexible, reusable, and high-performance code. This tutorial will guide beginners through the basics and practical examples.
TypeScript generics are a powerful feature that allows you to write flexible and reusable functions, classes, and interfaces. They enable your code to work with any data type while still providing strong type safety. Understanding how to use generics can help you write high-performance code by avoiding unnecessary type conversions and promoting better code reuse.
Let's start with a simple example that shows how generics work. Imagine you want a function that can return the first item of an array, but the array could contain any type of elements. Without generics, you might lose type information, but with generics, you can keep your code type-safe and flexible.
function firstItem<T>(arr: T[]): T {
return arr[0];
}
const num = firstItem([1, 2, 3]); // num is number
const str = firstItem(['a', 'b', 'c']); // str is stringIn this example,
Generics can also be used with interfaces and classes to create reusable components. For example, you can create a generic stack class that works with any type of data:
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
const numberStack = new Stack<number>();
numberStack.push(10);
console.log(numberStack.pop()); // 10
const stringStack = new Stack<string>();
stringStack.push('hello');
console.log(stringStack.pop()); // 'hello'This Stack class uses generics so it can store elements of any type while enforcing type safety. Using generics like this avoids duplicating code for different types and increases maintainability.
Sometimes you want to restrict the kinds of types that can be used with your generics. You can do this using constraints with the `extends` keyword. For example, if you want a function that accepts only objects with a `length` property, you can write:
function logLength<T extends { length: number }>(item: T): T {
console.log(item.length);
return item;
}
logLength('hello'); // 5
logLength([1, 2, 3]); // 3
// logLength(10); // Error: number doesn't have 'length'This restricts the generic type `T` to only those that have a `length` property. This is helpful for high-performance code because it prevents incorrect types from being used and enables more precise optimizations.
To wrap up, mastering TypeScript generics lets you write code that is not only flexible and reusable but also type-safe and performant. Use generic functions, classes, and constraints to tailor your code for any data type without sacrificing reliability or speed.
Keep practicing by refactoring your existing code to use generics where appropriate. You will soon see how this powerful feature can simplify your TypeScript projects and improve their performance.