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