Codectionary / Developer documentation / TypeScript

Generic Constraints

By default, a generic type parameter can be anything. The extends keyword constrains it to only types compatible with a given shape, letting you safely access specific properties or methods within the generic function while still supporting many different concrete types.

Syntax

function name<T extends Constraint>(param: T) { }

Examples

Constraining to Objects with a Property

Ensuring a generic type has at least a specific property before accessing it.

interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(item: T): T {
  console.log(`Length: ${item.length}`);
  return item;
}

logLength("hello");        // OK - strings have .length
logLength([1, 2, 3]);       // OK - arrays have .length
// logLength(42);            // Error - number has no .length property

keyof Constraint for Safe Property Access

A common pattern: constraining a key parameter to only the actual keys of an object.

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

const user = { name: "Alice", age: 25 };

const name = getProperty(user, "name"); // OK, correctly typed as string
// getProperty(user, "email");            // Error - "email" is not a key of user

Best practices

  • Use extends to constrain a generic parameter whenever the function body needs to access specific properties or methods on it
  • Use the K extends keyof T pattern for functions that access an object property by a dynamic key - it keeps both the object and the resulting value type-safe
  • Keep constraints as loose as possible while still enabling the functionality you need, to keep the generic function usable with the widest range of types
  • Combine multiple constraints with an intersection type (T extends A & B) when a generic parameter needs to satisfy more than one shape

At a glance

Purpose
Static types for JavaScript
File extension
.ts ยท .tsx
Runs in
Compiled to JavaScript
Usually used with
JavaScript and its ecosystem

Specifications & further reading

Related TypeScript documentation