Nice practical intro.
Just to add some terms, in case people wish to look further. The overall concept here are "parametric types" and "parametric functions", where "parameter" is referring to a type, as opposed to an "argument" which refers to a value to a function.
The term "generics" generally refers to parametric container types, and some limited functions. It's a useful, but perhaps less-than-complete form of parametric types, as the implementations usually have many limitations. Full parametric allow a kind of meta-programming, C++ style. Whether this is better or not depends greatly on the experience of the programmer.
Dynamically typed languages don't need parametric types as any container or function, can take any type at all. Though there's a related concept known as duck-typing that applies.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.