Polymorphism is the last important concept of OOP that you need to understand. Polymorphism basically means many forms/shapes, and it actually exists at different levels in OO languages.
First, functions can be polymorphic: you can create multiple variants of a given function that all accept arguments of different types. This is generally known as function overloading.
Another type of polymorphism is called parametric polymorphism, or generics, as we will see in the case of TypeScript. We will learn more about generics later in the book.
Another form of polymorphism is subtyping. For example, some programming languages allow you to define functions taking an object of the Animal type, but still work fine if passed an object that belongs to a subtype, like Dog. This type of polymorphism is usually referred to as the Liskov Substitution Principle.
A final form of polymorphism that we will consider is generally called duck typing, or structural typing. Structural typing is a concept that we already discussed in the first chapter and, as mentioned, is supported by TypeScript.