Understanding TypeScript Generics

September, 21st 2024 2 min read

TypeScript’s generics are one of the most powerful features in the language. They let you write components — functions, classes, and interfaces — that work with any data type while still preserving strict type safety.

Instead of writing the same function multiple times for different types, you write it once, and TypeScript infers the correct type during usage.

Generics eliminate duplication, prevent type errors, and help you write expressive, scalable code.

1. What Are Generics?

A generic is a placeholder type — like a variable for types. It appears in angle brackets <T> and can represent any type the user provides.

Basic example

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

identity(5);
identity("Hello");
identity({ a: 1 });

2. Why Use Generics?

Generics improve:

  • Type Safety
  • Reusability
  • Autocomplete quality

3. Generic Functions

ts
function getArray<T>(items: T[]): T[] {
  return [...items];
}

4. Generic Classes

ts
class Box<T> {
  constructor(public value: T) {}
}

5. Generic Constraints

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

6. Generic Interfaces

ts
interface Pair<T, U> {
  first: T;
  second: U;
}

7. Default Generic Types

ts
interface RequestConfig<T = string> {
  payload: T;
}

8. Built‑in Utility Types

TypeScript includes generic utilities such as:

  • Partial<T>
  • Readonly<T>
  • Record<K, T>
  • Pick<T, K>

9. Advanced Example: Generic Repository Pattern

ts
class Repository<T> {
  private items: T[] = [];
  add(item: T) { this.items.push(item); }
  getAll(): T[] { return this.items; }
}

Conclusion

Generics are essential for writing flexible, reusable, type‑safe TypeScript code.