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
Use Cases
Frequently Asked Questions
From the Blog
TypeScript Generics for Beginners
TypeScript generics let functions and types work with any type while preserving type safety. Learn generic functions, constraints, and everyday patterns.
Read More ProgrammingTypeScript for Beginners: JavaScript with a Safety Net
TypeScript adds optional static types to JavaScript, catching bugs before your code runs. This guide explains types, interfaces, generics, and the compile step clearly — with practical examples that show exactly why TypeScript makes large codebases easier to maintain.
Read More ProgrammingTypeScript for JavaScript Developers: A Quick Start
TypeScript adds static types to JavaScript, catching errors before you run code. This quick start covers types, interfaces, generics, and how to add it to a project.
Read More ProgrammingGo Explained: Types, Interfaces, and the Standard Library
Go's design is a series of deliberate refusals: no exceptions, no inheritance, no generics for a decade, one formatter. This guide explains what those refusals buy — explicit error paths, composition through small interfaces, and a standard library complete enough that most services need very few dependencies.
Read More