推荐答案
在 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; // 协变,允许赋值