协变与逆变
在 TypeScript 中,协变(covariance) 和 逆变(contravariance) 是类型系统处理 子类型关系 时的重要概念。不管是协变还是逆变本质上都是为了类型的安全
协变
- 子类型可以替换父类型
- 适用于:函数的返回值,参数赋值
ts
class Animal {}
class Dog extends Animal {}
type Fn1 = () => Dog
type Fn2 = () => Animal
let f1: Fn1 = () => new Dog()
let f2: Fn2
f2 = f1 // ✅ OK,因为 Dog 是 Animal 的子类型函数返回值为什么是协变?
原来期待的父类型,但是返回的是子类型,子类型具备所有父类型的属性,因此在实际使用子类型时是类型安全的
逆变
- 父类型可以替换子类型
- 适用于:函数参数
ts
class Animal {}
class Dog extends Animal {}
type Fn1 = (arg: Animal) => void
type Fn2 = (arg: Dog) => void
let f1: Fn1 = (a: Animal) => {}
let f2: Fn2
f2 = f1 // ✅ OK
// f1 = f2 // ❌ 不行为什么函数的形参是逆变?
f2系统期望的是类型Dog,但是实际运行的函数是f1,开发者会将类型Dog传入f1,f1期望的类型是Animal。此时类型安全
f1系统期望的是类型Animal,但是实际运行的函数是f2,开发者会将Animal传入f2,f2期望的类型是Dog,此时类型不安全
