我最近研究了 Typescript 中的generic概念。我无法理解“为什么函数与其参数存在逆变?”。我知道:
Covariance
是如果T extends U
(T
是 可分配 到 U
),则 G<T> extends G<U>
是真的(G<T>
也是 可分配 到 G<U>
)
Contravariance
是如果 T extends U
,则肯定会得出 G<U> extends G<T>
的结论(现在 G<U>
可以分配给 G<T>
)。
在这个论坛上提问之前,我阅读了以下帖子,但是,我仍然无法理解为什么 Typescript 中的函数的参数是逆变的:
我发现不仅函数与其参数在打字稿中是逆变的,其他一些语言也是如此。
在没有弄清楚为什么它是真的的情况下接受它,我感到非常沮丧。你能帮我解释一下吗?如果我缺少相关知识,请告诉我它是什么。
非常感谢您考虑我的问题。
我将使用
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 禁止这样做。