为什么打字稿中的函数与其参数存在逆变?

问题描述 投票:0回答:1

我最近研究了 Typescript 中的generic概念。我无法理解“为什么函数与其参数存在逆变?”。我知道:

  1. Covariance
    是如果
    T extends U
    T
    可分配
    U
    ),则
    G<T> extends G<U>
    是真的(
    G<T>
    也是 可分配
    G<U>

  2. Contravariance
    是如果
    T extends U
    ,则肯定会得出
    G<U> extends G<T>
    的结论(现在
    G<U>
    可以分配给
    G<T>
    )。

在这个论坛上提问之前,我阅读了以下帖子,但是,我仍然无法理解为什么 Typescript 中的函数的参数是逆变的

我发现不仅函数与其参数在打字稿中是逆变的,其他一些语言也是如此。

在没有弄清楚为什么它是真的的情况下接受它,我感到非常沮丧。你能帮我解释一下吗?如果我缺少相关知识,请告诉我它是什么。

非常感谢您考虑我的问题。

typescript contravariance generic-variance contravariant
1个回答
0
投票

我将使用

Animal
Dog
的具体示例。

class Animal {
  move(distanceInMeters: number = 0) {
    console.log(`Animal moved ${distanceInMeters}m.`);
  }
}
 
class Dog extends Animal {
  bark() {
    console.log("Woof! Woof!");
  }
}

允许在

Dog
Animal
之间进行分配有两种选择,我们是否可以用
Dog
代替
Animal
,以及我们是否可以用
Animal
代替
Dog

const animal: Animal = new Dog; 
animal.move(10);

因为

extends
代表我们有基地的成员,这样就可以了。打字稿允许这样做

const dog: Dog = new Animal;
dog.bark();

bark
中没有
Animal
方法,因此这会在运行时失败。 Typescript 禁止这样做。

现在让我们看看函数类型。

const dog: Dog = new Dog;
const animal: Animal = new Animal;

type UseAnimal: (animal: Animal) => void;
type UseDog: (dog: dog) => void;

const useAnimal: UseAnimal = (animal: Animal) { animal.move(10); }
const useDog: UseDog = (dog: Dog) { dog.bark() }

语言设计者对函数参数有相同的选择。让我们看看当我们允许这两种情况时会发生什么

const dogFn: UseDog = useAnimal;
dogFn(dog);

因为我们将

Dog
传递给
useAnimal
,所以可以
move(10)
如上所述。 Typescript 允许这样做。

const animalFn: UseAnimal = useDog;
animalFn(animal)

我们传递给

Animal
useDog
会导致运行时失败,因为它缺少
bark()
。 Typescript 禁止这样做。

© www.soinside.com 2019 - 2024. All rights reserved.