Advanced Types

Generics

Write reusable, type-safe code with generics — TypeScript's most powerful feature.

What are Generics?

Generics let you write code that works with multiple types without sacrificing type safety. Think of them as type-level variables.

Generic Constraints

You can constrain what types a generic accepts using extends.

Generic Interfaces and Classes

Generics work with interfaces and classes too, making it possible to build reusable data structures.

Built-in Generic Types

TypeScript includes many built-in generic utility types like Array<T>, Promise<T>, Record<K, V>, and more.

Example

typescript
// Simple generic function
function identity<T>(value: T): T {
  return value;
}

// Generic with constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { id: 1, name: "Alice", email: "alice@example.com" };
const name = getProperty(user, "name");   // type: string
const id = getProperty(user, "id");       // type: number

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

type UserResponse = ApiResponse<User>;
type ListResponse = ApiResponse<User[]>;

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

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

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

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }

  get size(): number {
    return this.items.length;
  }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 2

// Utility types
type Partial<T> = { [P in keyof T]?: T[P] };
type Readonly<T> = { readonly [P in keyof T]: T[P] };
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

type UserPreview = Pick<User, 'id' | 'name'>;
Try it yourself — TYPESCRIPT