Lesson 3 of 3

Generics and Utility Types

Master TypeScript generics and built-in utility types to write flexible, reusable, and type-safe code.

28 minutes

Generics and Utility Types

Generics allow you to write reusable, type-safe components.

Understanding Generics

Generics let you create components that work with multiple types:

function identity<T>(arg: T): T {
  return arg;
}
  • T is a type parameter (placeholder)
  • The actual type is determined when the function is called
  • Preserves type information throughout

Common Utility Types

TypeScript provides built-in utility types:

  • Partial<T>: Makes all properties optional
  • Required<T>: Makes all properties required
  • Pick<T, K>: Select specific properties
  • Omit<T, K>: Exclude specific properties
  • Record<K, V>: Create object type with keys K and values V

Generic Constraints

Limit what types can be used with extends:

function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

When to Use Generics

  • Reusable functions and classes
  • Data structures (arrays, maps, etc.)
  • API response wrappers

Code Example

// Generic function
function wrapInArray<T>(item: T): T[] {
  return [item];
}

const numbers = wrapInArray(42);      // number[]
const strings = wrapInArray("hello"); // string[]

// Generic interface
interface ApiResponse<T> {
  data: T;
  status: number;
  timestamp: Date;
}

// Using utility types
interface User {
  id: number;
  name: string;
  email: string;
  password: string;
}

type PublicUser = Omit<User, "password">;
type UserUpdate = Partial<Pick<User, "name" | "email">>;

// Generic with constraints
function merge<T extends object, U extends object>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

const result = merge({ name: "Alex" }, { age: 30 });
// result: { name: string; age: number; }