Start here. This is the direct spoken answer to practice first.
Overview
A useful generic preserves information between inputs and outputs. It should not merely replace a concrete type with a letter.
A generic lets an API express a relationship between types chosen by the caller. For example, an identity function returns the same type it receives rather than unknown. A constraint states what the implementation needs, such as requiring an id property, while preserving the rest of the caller's more specific type.