0Pricing
Frontend Academy · Lesson

Generics: T extends and constraints

Write generic functions and interfaces, constrain type parameters with extends, and use generic defaults for flexible APIs.

Generics: T extends and constraints is a free Frontend Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Are Generics?

Generics allow you to write functions, classes, and interfaces that work with multiple types while keeping type safety. Instead of writing separate functions for each type, you write one generic function parameterised by a type variable.

A Simple Generic Function

The type parameter T is declared in angle brackets. TypeScript infers T from the argument type — no explicit annotation needed at the call site.

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

identity(42);      // T is inferred as number, returns number
identity('hello'); // T inferred as string
identity<boolean>(true); // explicit

Generic Interfaces and Types

Parameterise interfaces and types with generics to describe reusable data structures.

interface Box<T> {
  value: T;
  label?: string;
}

const numBox: Box<number> = { value: 42 };
const strBox: Box<string> = { value: 'hello', label: 'greeting' };

extends — Constraining Generic Types

Use T extends SomeType to constrain what T can be. The function only accepts types that satisfy the constraint.

function getLength<T extends { length: number }>(item: T): number {
  return item.length; // safe: T is guaranteed to have length
}

getLength('hello');       // 5
getLength([1, 2, 3]);    // 3
getLength({ length: 7 }); // 7
// getLength(42);         // Error: number has no length

keyof and Generic Constraints

keyof T produces a union of T's property keys. Combined with generics, it enables type-safe property access.

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const user = { name: 'Alice', age: 30 };
getProperty(user, 'name');  // string
getProperty(user, 'age');   // number
// getProperty(user, 'foo'); // Error

Generic Defaults

Provide a default type for a generic parameter with T = DefaultType. Used when a sensible default exists but callers can override it.

interface Paginated<T = unknown> {
  items: T[];
  total: number;
  page: number;
}

const rawPage: Paginated = { items: [], total: 0, page: 1 };
const typedPage: Paginated<User> = { items: [], total: 0, page: 1 };

Multiple Type Parameters

Functions can have multiple independent type parameters.

function zip<A, B>(arrA: A[], arrB: B[]): Array<[A, B]> {
  return arrA.map((a, i) => [a, arrB[i]]);
}

zip([1, 2, 3], ['a', 'b', 'c']);
// [[1,'a'], [2,'b'], [3,'c']]

Generic Classes

Classes can be generic too. This is common in data structures like stacks, queues, and observable stores.

class Stack<T> {
  private items: T[] = [];
  push(item: T) { this.items.push(item); }
  pop(): T | undefined { return this.items.pop(); }
  peek(): T | undefined { return this.items.at(-1); }
  get size() { return this.items.length; }
}

const stack = new Stack<number>();
stack.push(1);
stack.push(2);
stack.pop(); // 2

Async Generic Functions

Generic async functions are common for typed API calls.

async function fetchJson<T>(url: string): Promise<T> {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json() as Promise<T>;
}

const users = await fetchJson<User[]>('/api/users');
const profile = await fetchJson<UserProfile>('/api/me');

Infer in Conditional Types

The infer keyword inside a conditional type extracts a type from a pattern. Used in library code to extract the return type of a function or element type of an array.

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type ElementType<T> = T extends Array<infer E> ? E : never;

type Fn = () => { name: string };
type Result = ReturnType<Fn>; // { name: string }

When to Use Generics

Use generics when: 1) the same logic applies to multiple types, 2) you need a relationship between input and output types, 3) you're building a reusable data structure or utility. Don't use generics just for the sake of it — concrete types are clearer when there's only one use case.

Quick Check

What does the constraint T extends { length: number } ensure?

Recap: Generics

Generics parameterise types so one function/class/interface works with multiple types. T extends SomeType adds constraints. keyof T gives property key unions. Generic defaults with T = Default. infer extracts types in conditional types. Use generics for reusable typed utilities and data structures.

Frequently asked questions

Is the “Generics: T extends and constraints” lesson free?

Yes — the full text of “Generics: T extends and constraints” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.

What will I learn in “Generics: T extends and constraints”?

Write generic functions and interfaces, constrain type parameters with extends, and use generic defaults for flexible APIs. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Frontend Academy?

No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Generics: T extends and constraints” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Frontend Academy lesson?

Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Generics: T extends and constraints
  2. Utility Types: Partial Required Pick Omit
  3. Mapped Types and Conditional Types
  4. Narrowing: typeof instanceof discriminated unions
← Back to Frontend Academy