From `any` to Awesome: Demystifying TypeScript Generics (Part 1)

TypeScript
Generics
Published: 10 June 2025

Ever copied a TypeScript snippet with <T> in it, crossed your fingers, and hoped it wouldn’t break things?

You're not alone.

Most of us start our TypeScript journey by ignoring generics altogether. We rely on any, or worse, let the type inference engine do all the heavy lifting, until things break in weird, hard-to-debug ways.

But here's the thing: generics aren’t scary once you understand why they exist and how to wield them. In fact, they’re one of the most powerful features TypeScript gives you.

Let's take a practical, example-first dive into generics.

Why should you even care about generics?

Let’s say you're building a dropdown component. You want it to work with both:

  • A list of countries: ['India', 'Japan', 'France']
  • A list of user objects: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

So you write this:

This works, but any throws away all type safety.

Now, rewrite it with generics:

Call it like this:

Now TypeScript knows what each item is. Autocomplete and type checking work perfectly.

What’s <T> and do you always need to write it?

<T> is a type variable, a placeholder.

When you write function renderDropdown<T>(...), you're saying:

This function takes a type T. I don't know what it is yet, but I’ll use it consistently.

But do you always need to write <T> yourself?

Not always.

When calling a generic function, TypeScript often infers the type:

But in the function definition, yes, you must declare <T>.

Arrow functions have quirks in TSX files:

Use explicit type annotation when:

  • Inference fails or gets too vague
  • You want to force a specific type
  • You're working with constraints or unions

Why do you use T and not something else?

You can name generics anything: X, Item, Banana.

But by convention:

  • T: main type
  • U: second type
  • V: value
  • R: return type
  • K: key

Use short names when the intent is obvious. Use descriptive names when clarity matters.

When should you build your own generics?

Use generics when:

  • You're writing reusable functions
  • You need to preserve or transform types across parameters/returns

Start with concrete types. Reach for generics only when you need flexibility without losing type safety.

Wrap-up

Generics let you define clear relationships between types, for example, connecting a function’s input to its output. They help TypeScript track and enforce consistent types, especially in cases where type inference alone isn’t enough.

You’ve seen how they work with simple functions, and why <T> matters in the first place. In real-world code, though, generics go much further.

In Part 2, we go beyond the basics. You’ll learn how to constrain generic types, set default values, and use conditional logic in type definitions. We’ll also look at how generics help with arrays, objects, and even real-world scenarios like API wrappers and reusable React components, all through example-first explanations.

Stay tuned!