Good Code
The good version stays generic while making the required updatedAt property part of the type contract.
Lesson 08
Constrain generics to the fields the function actually needs.
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),
);
}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),
);
}The good version stays generic while making the required updatedAt property part of the type contract.
The bad version accepts any item type and then escapes through any inside the implementation, so invalid calls compile and fail later.