推荐答案
在 TypeScript 中,协变 (Covariance) 和逆变 (Contravariance) 是描述类型系统中子类型关系的概念。
协变 (Covariance):如果类型
A
是类型B
的子类型,那么A[]
也是B[]
的子类型。换句话说,协变允许子类型关系在复合类型中保持一致。逆变 (Contravariance):如果类型
A
是类型B
的子类型,那么(arg: B) => void
是(arg: A) => void
的子类型。逆变反转了子类型关系。
对于函数类型:
- 函数参数类型是逆变的:因为函数参数类型需要更宽泛的类型来保证类型安全。
- 函数返回值类型是协变的:因为返回值类型需要更具体的类型来保证类型安全。
本题详细解读
协变 (Covariance)
协变描述的是子类型关系在复合类型中的传递性。例如,如果 Dog
是 Animal
的子类型,那么 Dog[]
也是 Animal[]
的子类型。这意味着你可以将一个 Dog[]
赋值给一个 Animal[]
类型的变量。
class Animal {} class Dog extends Animal {} let dogs: Dog[] = [new Dog()]; let animals: Animal[] = dogs; // 协变,允许赋值
逆变 (Contravariance)
逆变描述的是子类型关系在函数参数类型中的反转性。例如,如果 Dog
是 Animal
的子类型,那么 (arg: Animal) => void
是 (arg: Dog) => void
的子类型。这意味着你可以将一个接受 Animal
类型参数的函数赋值给一个接受 Dog
类型参数的函数类型的变量。
class Animal {} class Dog extends Animal {} let animalHandler: (arg: Animal) => void = (arg: Animal) => {}; let dogHandler: (arg: Dog) => void = animalHandler; // 逆变,允许赋值
函数参数类型和返回值类型
函数参数类型是逆变的:因为函数参数类型需要更宽泛的类型来保证类型安全。例如,如果你有一个函数
(arg: Animal) => void
,你可以将它赋值给(arg: Dog) => void
,因为Animal
是Dog
的超类型,函数可以处理更宽泛的类型。函数返回值类型是协变的:因为返回值类型需要更具体的类型来保证类型安全。例如,如果你有一个函数
(): Dog
,你可以将它赋值给(): Animal
,因为Dog
是Animal
的子类型,返回值可以更具体。
let getDog: () => Dog = () => new Dog(); let getAnimal: () => Animal = getDog; // 协变,允许赋值