方差 描述复合类型的子类型与其部分的子类型之间的关系 — 即何时 Container<Sub> 可以分配给 Container<Super>?
设 Dog 是 Animal 的子类型。
协变 — 保持方向(直观的情况)
ts
: [] = [];
: [] = dogs;
方差 描述复合类型的子类型与其部分的子类型之间的关系 — 即何时 Container<Sub> 可以分配给 Container<Super>?
设 Dog 是 Animal 的子类型。
: [] = [];
: [] = dogs;
返回类型和数组是 协变的:如果 Dog ⊆ Animal,则 Dog[] ⊆ Animal[]。返回 Dog 的函数可用于需要返回 Animal 的地方。
type Handler<T> = (arg: T) => void;
let animalHandler: Handler<Animal> = (a) => {};
let dogHandler: Handler<Dog> = animalHandler; // ✅ (with strictFunctionTypes)
// a handler that accepts ANY Animal can safely handle a Dog
函数 参数 是逆变的:Handler<Animal> 可分配给 Handler<Dog>,这与元素关系 相反。这是合理的 — 处理所有动物的东西肯定也能处理狗。
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript 仅在 strictFunctionTypes 下对独立函数类型进行逆变检查;方法参数出于易用性考虑是故意 双变的,这在技术上是不合理的。
方差解释了 为什么 某些赋值被允许或被拒绝 — 为什么 Dog[] 适配 Animal[],但 (d: Dog) => void 回调不能始终代替 (a: Animal) => void。
理解它可以帮助你设计通用 API(例如只读与写入位置)并解读涉及函数和泛型的令人困惑的「不可分配」错误。