There are times when you want to write a function which works with a wide variety of types. The canonical example is the identity function, beloved by functional programmers.

const identity = x => x

In this situation, you could use the standard TypeScript escape hatch: the any type.

const identity = (x: any): any => x

Unfortunately, this discards any type information gleaned from the function parameter. As far as the TypeScript compiler is concerned, you could be returning anything.

Generics are TypeScript's answer to this problem:

const identity = <T>(x: T): T => x

Think of the angle brackets (<>) as a placeholder for type information, which is filled when the function is called. For example:

identity<string>('123') // Returns a string
identity<number>(123) // Returns a number
identity<boolean>(1) // Type error