1. 协变与逆变的本质差异
协变(Covariance)和逆变(Contravariance)是类型系统中描述继承关系方向性的核心概念。它们本质上解决的是"当存在继承关系时,复合类型(如容器、函数参数等)的兼容性如何传递"的问题。
1.1 协变:保持继承方向
协变最直观的理解是"子类可以替代父类"。在类型系统中表现为:如果Cat是Animal的子类,那么List<Cat>也可以被视为List<Animal>的子类。这种关系方向与原始类型继承方向一致,因此称为"协"变(共同变化)。
实际案例:
typescript复制class Animal {}
class Cat extends Animal {}
// 协变示例:Cat[] 可以赋值给 Animal[]
const animals: Animal[] = [new Cat()]; // ✅
1.2 逆变:反转继承方向
逆变则相反,表现为"父类可以替代子类"。典型场景是函数参数:如果Cat是Animal的子类,那么(Animal) => void反而可以视为(Cat) => void的子类。这种关系方向与原始继承方向相反,因此称为"逆"变。
实际案例:
typescript复制type AnimalHandler = (a: Animal) => void;
type CatHandler = (c: Cat) => void;
// 逆变示例:AnimalHandler 可以赋值给 CatHandler
const handleCat: CatHandler = (animal: Animal) => {}; // ✅
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 类型安全的数学原理
2.1 里氏替换原则(LSP)
协变和逆变的设计都遵循Barbara Liskov提出的著名原则:
如果S是T的子类型,那么程序中T类型的对象可以被替换为S类型的对象,而不会改变程序的任何期望属性。
- 协变遵守LSP:
List<Cat>作为List<Animal>使用时,所有操作仍然安全 - 逆变也遵守LSP:
(Animal)=>void作为(Cat)=>void使用时,调用者传入的Cat必然满足Animal的约束
