TypeScript 比较两个类型并非通过类型的名称,而是比较这两个类型上实际拥有的属性与方法
class Cat {
eat() {}
}
class Dog {
eat() {}
}
function feedCat(cat: Cat) {}
feedCat(new Dog()) // 正常
结构类型的别称鸭子类型(Duck Typing),这个名字来源于鸭子测试(Duck Test)。其核心理念是,如果你看到一只鸟走起来像鸭子,游泳像鸭子,叫得也像鸭子,那么这只鸟就是鸭子
class Cat {
meow() {}
eat() {}
}
class Dog {
eat() {}
}
function feedCat(cat: Cat) {}
feedCat(new Dog()) // 报错!
// ---
class Cat {
eat() {}
}
class Dog {
bark() {}
eat() {}
}
function feedCat(cat: Cat) {}
feedCat(new Dog())
结构化类型系统认为 Dog 类型完全实现了 Cat 类型。至于额外的方法 bark,可以认为是 Dog 类型继承 Cat 类型后添加的新方法,即此时 Dog 类可以被认为是 Cat 类的子类
面向对象编程中的里氏替换原则也提到了鸭子测试:如果它看起来像鸭子,叫起来也像鸭子,但是却需要电池才能工作,那么你的抽象很可能出错了
标称类型系统(Nominal Typing System)要求,两个可兼容的类型,其名称必须是完全一致的