Generics
Generics allow functions, classes, and interfaces to be written in terms of placeholder types that are specified when the code is actually used, enabling reusable, type-safe code without duplicating logic for each concrete type.
Definition
Generics allow functions, classes, and interfaces to be written in terms of placeholder types that are specified when the code is actually used, enabling reusable, type-safe code without duplicating logic for each concrete type.
Overview
Generics solve a specific tension in statically typed languages: without them, you either write the same function or class separately for every type you want to support, or you use a loose type like `any`/`Object` and lose compile-time type safety. TypeScript, Java, C#, and Rust all support generics, typically written with angle-bracket syntax like `Array<T>` or `List<T>`, where `T` is a placeholder that gets replaced with a concrete type at the point of use. A generic function or class is defined once but works correctly across many types, with the compiler verifying that operations performed inside the generic code are valid for whatever type is eventually substituted in. For example, a generic `identity<T>(value: T): T` function can accept and return a number, a string, or a custom object, and the type checker still knows the exact return type based on what was passed in — this is a core feature that distinguishes static typing with generics from dynamically typed code that achieves similar flexibility only at runtime. Generics interact closely with interfaces: generic constraints let you say 'this type parameter must implement interface X,' which lets generic code call methods on the type parameter safely while still working across many concrete implementations. This combination is what makes collection classes — generic lists, maps, and sets — both flexible and type-safe. Without generics, developers historically resorted to either code duplication (writing a separate class per type) or unsafe casting from a loosely-typed container, both of which generics were specifically designed to eliminate while preserving the compile-time guarantees offered by static typing.
Key Concepts
- Placeholder type parameters (commonly written as T, K, V) filled in at usage time
- Enables reusable code without sacrificing compile-time type safety
- Supported by TypeScript, Java, C#, Rust, and many other statically typed languages
- Generic constraints restrict type parameters to types implementing specific interfaces
- Backbone of type-safe collection classes (generic lists, maps, sets)
- Compiler infers and checks concrete types at each call site
- Avoids both code duplication and unsafe type casting