tezvyn:

TypeScript Generics: Writing Functions That Adapt to Types

AI-drafted, machine-checkedSource: typescriptlang.orgintermediate

TypeScript generics create functions with type placeholders, capturing an input's type to inform the output's. This is vital for reusable components that work on various data types.

WHY IT EXISTS Software engineering aims to build reusable components. Without generics, you face a bad choice: either write a separate function for every single data type, or write one function that uses the any type, which sacrifices type safety. Generics were created to solve this by enabling flexible, reusable, and type-safe components.

THE MENTAL MODEL A generic is a type placeholder. Think of it as a variable, but for types instead of values. You define a function with a placeholder like <T>, and then you can use T inside that function's signature. When the function is called, TypeScript fills in that placeholder with the concrete type you provided, ensuring type safety flows from input to output.

HOW IT WORKS You introduce a type variable using angle brackets, like <Type>, in a function's definition. This variable can then be used to type arguments and return values. For example, in function identity<T>(arg: T): T, the T captures the type of arg. If you pass a string, TypeScript knows T is string and therefore the function must return a string. This allows the compiler to track the type, unlike with any where that information is lost.

WHEN TO USE IT Use generics whenever you're building a component—be it a function, class, or interface—that needs to work over a variety of types while maintaining a connection between them. This is fundamental for creating reusable utility functions (like identity or firstElement), data structures (like Array<T>), or API wrappers that should work for different data payloads.

WHEN NOT TO USE IT If a function works on only one specific type and will never need to work on another, generics are unnecessary overhead. For instance, a calculateArea function that always expects a number for a radius does not need to be generic. Also, if the types of the inputs and outputs have no relationship, generics may not be the right tool.

ONE CANONICAL EXAMPLE The identity function is the "hello world" of generics. A naive version using any (function identity(arg: any): any) loses type information. The generic version preserves it: function identity<T>(arg: T): T { return arg; }. If you call let output = identity("myString");, the type of output is correctly inferred as string. If you had used the any version, its type would be any, and you would lose TypeScript's compiler support.

Read the original → typescriptlang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.