Functions and generics

Constrain a generic only when necessary

Require a capability from a type parameter while preserving the caller-specific type in the result.

A generic preserves a relationship between caller-specific types. A constraint adds the minimum capability the implementation needs:

function longest<T extends { length: number }>(a: T, b: T): T {
  return a.length >= b.length ? a : b
}

Strings and arrays both work because they have a numeric length. A number fails because it does not.

The return type remains T, not just { length: number }. Passing two string arrays produces a string-array result.

A constraint is not permission to create any matching object and return it as T:

function broken<T extends { length: number }>(value: T): T {
  return { length: value.length }
}

The object satisfies the constraint, but it may lack caller-specific properties required by T. TypeScript correctly rejects it.

Use a generic when a type parameter relates two or more positions. If it appears only once, a normal parameter type is usually clearer.

Exercise: call longest() with two objects that also have a label. Confirm that the returned value keeps the label type.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →