stackademic

The leading education platform for anyone with an interest in software development.

Generics

Write reusable functions and types that work across type parameters

Overview

Generics let you parameterize types. A generic function or interface works with multiple types while preserving type relationships—avoiding any and unsafe casts.

Syntax / Usage

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

const n = identity(42)       // number
const s = identity('hello')  // string

// Multiple type parameters
function pair<A, B>(a: A, b: B): [A, B] {
  return [a, b]
}

// Constrained generics
interface HasId { id: string }

function findById<T extends HasId>(items: T[], id: string): T | undefined {
  return items.find((item) => item.id === id)
}

// Generic interface
interface ApiResult<T> {
  data: T
  error: string | null
}

Examples

Generic React props:

interface ListProps<T> {
  items: T[]
  renderItem: (item: T) => React.ReactNode
  keyExtractor: (item: T) => string
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return (
    <ul>
      {items.map((item) => (
        <li key={keyExtractor(item)}>{renderItem(item)}</li>
      ))}
    </ul>
  )
}

Factory with default type:

function createStore<T = string>(initial: T) {
  let state = initial
  return {
    get: () => state,
    set: (value: T) => { state = value },
  }
}

Common Mistakes

  • Over-genericizing simple functions that only use one type
  • Forgetting constraints when accessing properties on T
  • Using generics when a union or overload is simpler
  • Inference failures—annotate call sites when needed

See Also

interfaces utility-types unions type-guards