TypeScript

Lesson 08

Generic constraints

Constrain generics to the fields the function actually needs.

Good Code

sort-by-updated.ts
type HasUpdatedAt = {
  updatedAt: string;
};

function sortByUpdatedAt<T extends HasUpdatedAt>(items: T[]): T[] {
  // The constraint keeps the required field in the contract.
  return [...items].sort((left, right) =>
    right.updatedAt.localeCompare(left.updatedAt),
  );
}

Bad Code

sort-by-updated.ts
function sortByUpdatedAt<T>(items: T[]): T[] {
  // any hides the missing constraint until runtime.
  return [...items].sort((left, right) =>
    (right as any).updatedAt.localeCompare((left as any).updatedAt),
  );
}

Review Notes

What to review

Good Code

The good version stays generic while making the required updatedAt property part of the type contract.

Bad Code

The bad version accepts any item type and then escapes through any inside the implementation, so invalid calls compile and fail later.

Takeaways

  • Use `extends` to keep generic functions flexible without losing the properties they rely on.