TypeScript Generics Explained with Easy Examples
A generic in TypeScript is a way to write reusable code that works with different types without hardcoding them.
It’s not a variable or a function — it’s a type placeholder like <T>
that lets you plug in a real type later.
function identity<T>(arg: T): T {
return arg;
}
let a = identity<string>("Hello");
let b = identity<number>(123);
Here, T
is just a placeholder for a type. You can reuse the same function with different types.
Explained Simply
function identity<T>(arg: T): T {
return arg;
}
T
is not a variable. It’s a type parameter.arg
is a regular variable, but its type depends on the type you pass in.identity
is a function that uses a generic to work with any type.
This lets you write flexible code that works with many types without repeating the same logic.
A Generic Is a Feature, Not a Function
Generics are not functions — they’re a feature that lets you use type placeholders to make your code reusable and type-safe.
You’re basically telling TypeScript:
“I don’t know the exact type yet, but when this code is used, I’ll fill it in.”
Analogy: Cookie Cutter
Imagine a function is like a cookie cutter.
- Use vanilla dough (type
string
) → you get a string. - Use chocolate dough (type
number
) → you get a number.
The cutter stays the same. Only the dough (type) changes. That’s the power of generics.
Generics in Interfaces
interface Box<T> {
content: T;
}
let stringBox: Box<string> = { content: "hello" };
let numberBox: Box<number> = { content: 42 };
Generics in Classes
class Container<T> {
value: T;
constructor(value: T) {
this.value = value;
}
}
const c = new Container<boolean>(true);
Generics with Arrays
function getFirstElement<T>(arr: Array<T>): T {
return arr[0];
}
const firstString = getFirstElement<string>(["apple", "banana", "cherry"]);
const firstNumber = getFirstElement<number>([10, 20, 30]);
Array<T>
is a built-in generic. You can also write it as T[]
.
Restricting Generic Types
You can use extends
to make sure T
has certain properties.
function getLength<T extends { length: number }>(item: T): number {
return item.length;
}
getLength("hello"); // OK
getLength([1, 2, 3]); // OK
getLength({ length: 99 }); // OK
// getLength(123); ❌ Error: number doesn’t have length
Multiple Type Parameters
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
const result = mergeObjects({ name: "Alice" }, { age: 30 });
This combines the properties of both objects into one.
Default Generic Type
function createList<T = string>(items: T[]): T[] {
return items;
}
const list1 = createList(["a", "b", "c"]); // T = string (default)
const list2 = createList<number>([1, 2, 3]); // T = number
You can set a default type so that it’s used when the caller doesn’t specify one.
Common Question
Does a generic create a “universal variable”?
No. A generic creates a structure (like a function or class) where types are filled in later. It’s not a variable itself.
T
is a type placeholder, not a value.- Generics only exist at compile time for type checking.
- They disappear in the final JavaScript code.