← Back to Blog
console.log()

TypeScript Generics Explained Simply

Understand TypeScript generics with clear examples. Learn to write flexible, reusable, and type-safe code.

typescriptjavascriptprogramming

TypeScript Generics Explained

Generics let you write flexible code without sacrificing type safety. Let's understand them step by step.

Why Generics?

Without generics, you'd have to write multiple functions:

function identityString(arg: string): string {
 return arg;
}

function identityNumber(arg: number): number {
 return arg;
}

With generics, one function handles all types:

function identity<T>(arg: T): T {
 return arg;
}

identity<string>("hello"); // Type: string
identity<number>(42); // Type: number
identity("inferred"); // Type: string (inferred)

Generic Interfaces

Create flexible data structures:

interface Box<T> {
 value: T;
 getValue(): T;
}

const stringBox: Box<string> = {
 value: "hello",
 getValue() { return this.value; }
};

Generic Constraints

Limit what types are acceptable:

interface HasLength {
 length: number;
}

function logLength<T extends HasLength>(arg: T): number {
 console.log(arg.length);
 return arg.length;
}

logLength("hello"); // OK - strings have length
logLength([1, 2, 3]); // OK - arrays have length
logLength(123); // Error - numbers don't have length

Multiple Type Parameters

Use multiple generics together:

function pair<K, V>(key: K, value: V): [K, V] {
 return [key, value];
}

const result = pair("age", 25); // Type: [string, number]

Generic Classes

Build reusable class patterns:

class Stack<T> {
 private items: T[] = [];

 push(item: T): void {
 this.items.push(item);
 }

 pop(): T | undefined {
 return this.items.pop();
 }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);

Real-World Example: API Response

interface ApiResponse<T> {
 data: T;
 status: number;
 message: string;
}

interface User {
 id: number;
 name: string;
}

async function fetchUser(): Promise<ApiResponse<User>> {
 // ...
}

Conclusion

Generics are essential for writing professional TypeScript. They give you flexibility while maintaining type safety.