Mastering TypeScript Generics: A Practical Guide
Mastering TypeScript Generics: A Practical Guide
TypeScript generics enable you to write flexible, reusable code while maintaining type safety. Let's dive into practical examples that you can apply immediately.
Understanding the Basics
At its core, a generic is a type placeholder. Think of it as a variable, but for types:
function identity<T>(arg: T): T {
return arg;
}
// T becomes 'string'
const str = identity("hello");
// T becomes 'number'
const num = identity(42);
Constraining Generics
Sometimes you need to ensure the generic type has certain properties:
interface HasLength {
length: number;
}
function logLength<T extends HasLength>(arg: T): T {
console.log(arg.length);
return arg;
}
Generic Utility Types
TypeScript provides powerful built-in utility types:
// Make all properties optional
type PartialUser = Partial<User>;
// Make all properties required
type RequiredUser = Required<User>;
// Pick specific properties
type UserName = Pick<User, 'firstName' | 'lastName'>;
Real-World Patterns
Here's a pattern I use frequently for API responses:
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
const response = await fetch(url);
return response.json();
}
Conclusion
Generics are essential for writing maintainable TypeScript. Start simple, and gradually incorporate more advanced patterns as you become comfortable.
Enjoyed this article? Share it with others.