When working with TypeScript, you quickly run into a common problem:
👉 You want your code to be reusable, but also type-safe.
At first, it’s tempting to use any to make things flexible… but that comes at a cost:
- You lose type safety
- You lose autocomplete
- You introduce hidden bugs
This is exactly the problem that TypeScript Generics solve.
They let you write reusable code without sacrificing type safety.
In this article, we’ll explore:
- What Generics are
- What problem they solve
- Practical examples you’ll actually use
- Best practices to avoid common mistakes
Let’s dive in.
🤔 Problem with type reusability
When you want your function to be reusable, you usually end up with this any approach:
function identity(value: any): any {
return value
}
It works but it also comes with problems such as no type safety, no IntelliSense, and can easily lead to break things.
The second problem is code duplication:
function identityString(value: string): string {
return value
}
function identityNumber(value: number): number {
return value
}
With this approach, we are breaking the Don't Repeat Yourself (DRY) rule which also makes the code harder to maintain and less scalable.
🤔 Solution: TypeScript Generics
Generics allow you to create components, functions, or classes that work with multiple types, while still preserving full type information.
Think of them as:
👉 “Type placeholders” that get filled in later
Basic example:
function identity<T>(value: T): T {
return value
}
Here:
-
Tis a generic type - It represents whatever type you pass in
Usage:
identity<string>("hello") // string
identity<number>(123) // number
TypeScript automatically knows what comes out based on what goes in.
🟢 Practical Examples
Let’s look at real-world scenarios where generics shine.
✅ Example 1: Reusable API Response Type
Very common pattern in frontend apps:
type ApiResponse<T> = {
data: T
error: string | null
}
Usage:
type User = {
id: number
name: string
}
const response: ApiResponse<User> = {
data: { id: 1, name: "John" },
error: null
}
Now your API types are consistent, reusable, and fully typed.
✅ Example 2: Generic Array Helper
function getFirstItem<T>(arr: T[]): T {
return arr[0]
}
Usage:
const number = getFirstItem([1, 2, 3]) // number
const string = getFirstItem(["a", "b"]) // string
TypeScript knows exactly what type is returned.
✅ Example 3: Generic Props in Vue
Check out my other article where I have explained this topic in more details here.
✅ Example 4: Constraining Generics
Sometimes you want flexibility — but with rules.
function getLength<T extends { length: number }>(value: T) {
return value.length
}
Usage:
getLength("hello") // ✅
getLength([1, 2, 3]) // ✅
getLength(123) // ❌ error
With this approach, you ensure flexibility but also controlled structure.
✅ Example 5: Keyof + Generics
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
Usage:
const user = {
id: 1,
name: "John"
}
getProperty(user, "name") // ✅
getProperty(user, "age") // ❌ error
This is extremely powerful for forms, dynamic access, or utilities.
📖 Learn more
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉
🧪 Advance skills
A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.
Check out Certificates.dev by clicking this link or by clicking the image below:
Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!
✅ Summary
TypeScript Generics are one of the most powerful features in the language. They let you write code that is both flexible and safe — which is exactly what you want in modern applications.
Once you start using them properly, it’s hard to go back.
Take care!
And happy coding as always 🖥️


Top comments (0)