Generics

The Cache That Almost Crashed Our Database

It was 2:15 PM on a Tuesday when our database server's CPU hit 98%. Queries that took 5ms were timing out. Our ops team was preparing to scale up the instance – a $3,000/month increase.

I checked our application code and found the culprit:

// cache.js - Our old JavaScript cache
class Cache {
  constructor() {
    this.data = new Map();
  }
  
  get(key) {
    return this.data.get(key);  // What type is this?
  }
  
  set(key, value) {
    this.data.set(key, value);  // What type is value?
  }
}

// Usage
const userCache = new Cache();
userCache.set('user-123', { id: '123', name: 'John' });

const user = userCache.get('user-123');
console.log(user.name);  // Works

// But then someone did this:
const productCache = new Cache();
productCache.set('prod-456', '{"id":"456","name":"Laptop"}');  // String instead of object!

const product = productCache.get('prod-456');
console.log(product.price);  // Undefined! Should have been parsed first

Without types, developers stored raw JSON strings instead of parsed objects. The app repeatedly parsed the same JSON and hit the database when it failed. Result: 15,000 unnecessary database queries per minute.

I rewrote it with TypeScript generics:

Result: Type errors caught at compile time. Database load dropped to normal. Saved $3,000/month.

This article covers generics – TypeScript's most powerful feature for building reusable, type-safe code.


Generic Functions

Functions that work with multiple types while preserving type information.

Basic Generic Function

Generic Array Functions

Multiple Type Parameters

Real-World Example: API Wrapper


Generic Constraints

Restrict generic types to types with specific properties.

extends Constraint

Constraining to Object Types

Multiple Constraints


Generic Interfaces

Interfaces with type parameters.

Basic Generic Interface

Generic Interface with Multiple Parameters

Real-World Example: Repository Pattern


Generic Classes

Classes with type parameters.

Basic Generic Class

Generic Class with Constraints

Real-World Example: Event Emitter


Default Type Parameters

Provide default types for generics.

Basic Default Type

Default with Constraints


Generic Utility Functions

Build reusable utility functions with generics.

Map Function

Filter Function

Reduce Function


Advanced Generic Patterns

Generic Factory Function

Generic Mixin Pattern

Conditional Types with Generics


Real-World Example: Type-Safe State Management


Common Mistakes I Made

1. Not Using Generic Constraints

Bad:

Good:

2. Over-Complicating with Generics

Bad:

Good:

3. Forgetting Generic Constraints

Bad:

Good:


Your Challenge

Build a type-safe query builder:


Key Takeaways

  1. Generics preserve type information - work with any type safely

  2. Generic constraints - restrict types with extends

  3. Generic interfaces - reusable type-safe contracts

  4. Generic classes - type-safe data structures

  5. Default type parameters - provide sensible defaults

  6. keyof constraint - type-safe property access

  7. Don't over-use - generics add complexity, use when needed


What I Learned

The database overload incident taught me: generics are about type preservation, not type flexibility.

Without generics:

We stored strings when we meant to store objects. The cache became unreliable. Type information was lost. Result: 15,000 unnecessary database queries per minute.

With generics:

Type information flows through. The compiler catches mistakes. The cache does what it promises.

The $3,000/month savings came from type safety.

Generics aren't about writing less code – they're about writing correct code. They turn "this probably works" into "the compiler guarantees it works."

Use generics to make impossible states impossible. Let TypeScript prove your code correct.


Next: Type Manipulation & Utility Types

In the next article, we'll explore TypeScript's advanced type manipulation features. You'll learn how mapped types and conditional types helped me refactor a 50,000-line codebase with zero runtime errors.

Last updated