# Understanding TypeScript Generics: Write Flexible, Reusable Code
When working with TypeScript, one of the most powerful features you’ll encounter is generics. If you've ever found yourself duplicating code just to handle different data types, generics are the solution you’ve been looking for.
Let’s break it down in a practical and developer-friendly way.
What Are Generics?
Generics allow you to write code that works with multiple types instead of a single one. Think of them as placeholders for types.
Instead of saying:
“This function only works with strings”
You say:
“This function works with any type—and I’ll decide that type later.”
Basic Example
Without generics:
function identity(value: string): string {
return value
}
This only works with strings.
With generics:
function identity<T>(value: T): T {
return value
}
Now it works with any type:
identity<string>("Hello")
identity<number>(42)
identity<boolean>(true)
Why Use Generics?
1. Reusability
You write code once and use it with different types.
2. Type Safety
You still get full TypeScript type checking.
3. Cleaner Code
No need to create multiple versions of the same function.
Generics with Arrays
function getFirstItem<T>(arr: T[]): T {
return arr[0]
}
Usage:
getFirstItem<number>([1, 2, 3])
getFirstItem<string>(["a", "b", "c"])
Generics in Interfaces
interface ApiResponse<T> {
data: T
status: number
}
Usage:
const userResponse: ApiResponse<{ name: string }> = {
data: { name: "Norman" },
status: 200
}
Generics in Classes
class Box<T> {
content: T
constructor(value: T) {
this.content = value
}
}
Usage:
const numberBox = new Box<number>(123)
const stringBox = new Box<string>("Hello")
Generic Constraints
Sometimes you want to limit what types can be used.
function printLength<T extends { length: number }>(item: T): void {
console.log(item.length)
}
This ensures only types with a length property are allowed.
Multiple Generics
function pair<K, V>(key: K, value: V) {
return { key, value }
}
Usage:
pair<string, number>("age", 25)
Default Generic Types
function createArray<T = string>(length: number, value: T): T[] {
return Array(length).fill(value)
}
If no type is provided, it defaults to string.
Real-World Example (API Fetching)
async function fetchData<T>(url: string): Promise<T> {
const response = await fetch(url)
return response.json()
}
Usage:
type User = {
id: number
name: string
}
const user = await fetchData<User>("/api/user")
Common Mistakes
Overusing Generics
Don’t use generics when a specific type is enough.
Ignoring Type Inference
TypeScript can often infer the type automatically:
identity("Hello") // no need for <string>
When Should You Use Generics?
Use generics when:
You want reusable components/functions
You don’t know the type ahead of time
You want flexibility without losing type safety
Final Thoughts
Generics are a game-changer in TypeScript. They help you write cleaner, reusable, and safer code especially in large-scale applications.
About the author
I’m a passionate Software Developer with 2 years of hands-on experience building full-stack web applications that are clean, scalable, and user-friendly. With a strong foundation in modern frameworks like Laravel and Vue.js, I enjoy crafting digital solutions that not only work well but also deliver real value. My journey in software development has been driven by curiosity, creativity, and a love for solving real-world problems through code. Whether it's building RESTful APIs, designing responsive UIs, or optimizing performance, I’m always eager to learn, improve, and push boundaries. Currently, I’m focused on expanding my skills in Kibana, Elasticsearch, and scalable architecture for production-ready applications. 🚀 Let’s build something great together.
Comments
Join the discussionNo comments yet. Be the first to comment.