Lesson 17 +10 XP

Generic Constraints

Generic Constraints

Sometimes a generic type parameter needs to support specific properties or methods. Use the extends keyword to enforce Generic Constraints.

Constraining Generics (extends)

interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(arg: T): T {
  console.log(arg.length); // Safe! Guaranteed to have .length property.
  return arg;
}

logLength("hello");       // Valid (string has .length)
logLength([1, 2, 3]);     // Valid (array has .length)
// logLength(123);        // Error: Argument of type 'number' is not assignable to 'Lengthwise'.

Using keyof in Constraints

Ensure a key exists on an object using <K extends keyof T>:

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

const user = { name: "Alice", age: 30 };
let name = getProperty(user, "name"); // Type 'string'
// getProperty(user, "email");       // Error: Argument of type '"email"' is not assignable to '"name" | "age"'.

TL;DR

  • Use <T extends Boundary> to restrict generic type parameters to sub-types of Boundary.
  • <K extends keyof T> locks keys to actual valid properties of an object type.