TypeScript Generics
Generics let you write reusable code that works with any type while maintaining type safety.
What Are Generics?
Generics are type placeholders specified when the code is used:
function identity<T>(value: T): T {
return value;
}
let num = identity<number>(42); // number
let str = identity<string>("hello"); // string
Why generics? They let you write functions that work with multiple types without losing type safety.
Generic Functions
Type parameters are inferred from arguments automatically:
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
let combo = pair("hello", 42); // [string, number]
Generic Interfaces and Classes
Interfaces and classes can also be generic:
interface Container<T> {
value: T;
getValue(): T;
}
class Stack<T> {
private items: T[] = [];
push(item: T): void { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
}
let numberStack = new Stack<number>();
numberStack.push(1);
Generic Constraints
Use extends to restrict what types can be used:
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(item: T): void {
console.log(item.length);
}
logLength("hello"); // OK
logLength([1, 2, 3]); // OK
// logLength(42); // Error: number doesn't have length
Tip: Constraints ensure generic code only works with types that have the required properties.
Default Type Parameters
TypeScript allows default types when none is specified:
interface Response<T = string> {
data: T;
status: number;
}
let textResponse: Response = { data: "hello", status: 200 };
let numResponse: Response<number> = { data: 42, status: 200 };
Key Utility Pattern
Use keyof for type-safe property access:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let name = getProperty({ name: "John", age: 25 }, "name");
Best Practices
- Use generic constraints to ensure types have required properties
- Let TypeScript infer types when possible
- Use default type parameters for common combinations
- Keep generics simple — don’t over-complicate type parameters
- Use
keyoffor type-safe property access
Common Mistakes
- Using generics without constraints when the type needs specific properties
- Specifying too many type parameters makes code harder to read
- Always specifying type parameters explicitly instead of inferring
- Using
anyinside generics defeats their purpose