Generics are a way to make code reusable through type abstraction. If you have a part of your system (a class, function, interface, etc.) that works with a single type, Generics allow it to work with multiple types.
Let's look at an example
We are building REST API and want to standardize backend responses by wrapping the data in an data object. Since we have many entities, we would have to duplicate the interfaces for each of them. And if we later want to change error: string to something else, for example to a ApiError class, we would have to do it for every interface separately.
This is exactly the problem that Generics solve. Instead of duplicating code, we create a single generic type and extend it.
The same can be done with classes, interfaces, and functions. But to understand the idea and the problem that Generics solve, this example is more than enough.