Back to roadmaps typescript Course

Generic Constraints and keyof

While generics can accept any type, there are times when you need to write a generic function that requires a minimum set of properties. To do this, we use Generic Constraints.


1. Using extends for Constraints

Suppose you want a function that logs the length of an object. If you use a free generic T, the compiler raises an error because it cannot guarantee the object contains a length property.

// This fails compilation:
// function logLength<T>(arg: T) {
//   console.log(arg.length);
// }

We can fix this by creating an interface that describes our requirement and using the extends keyword to constrain our type variable:

interface Lengthwise {
  length: number;
}

function logLength<T extends Lengthwise>(arg: T): void {
  console.log(arg.length); // Now safe to access
}

logLength("hello"); // Valid (strings have a length property)
logLength([1, 2, 3]); // Valid (arrays have a length property)
// logLength(42); // Error: Argument of type 'number' is not assignable.

2. The keyof Operator

The keyof operator takes an object type and produces a union of its keys (property names).

interface UserProfile {
  id: string;
  name: string;
  email: string;
}

// UserKeys is "id" | "name" | "email"
type UserKeys = keyof UserProfile;

3. Combining keyof and Constraints

You can combine generic constraints and the keyof operator to build highly type-safe helpers, such as a function that retrieves a property value from an object by its key.

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

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

const userName = getProperty(user, "name"); // Returns string
// getProperty(user, "email"); // Error: Argument of type '"email"' is not assignable.

By using K extends keyof T, TypeScript prevents developers from passing non-existent property names.


4. Summary

  • Use T extends Interface to restrict generic type variables to shapes that include specific fields.
  • The keyof operator creates a union type containing all string and numeric keys of an object structure.
  • Combine keyof and generic constraints to safely access object properties dynamically.
Published on Last updated: