An important feature of the type system of TypeScript is that it's structurally typed. Formally this means that the types equivalence and compatibility are determined by the structure of the types, not by other characteristics such as name or inheritance hierarchy.
This may sound quite abstract at first, so let's take a look at a specific example:
// ch4/structural-typing/example.ts
interface Namable {
name: string;
}
class Cat {
name: string;
}
class Castle {
name: string;
capacity: string;
}
const formatName = (obj: Namable) => `The name is ${obj.name}`;
The preceding snippet defines an interface called Namable, which has a declaration of a single property called name. We also define the Cat and Castle classes: both of them having a name property but neither of them implementing the Namable interface.
If we invoke formatName with a new...