Typescript中的协变、逆变、双向协变
协变(Covariant)、逆变(Contravariant)、双向协变(Bivariant)并非Typescript所特有,其他结构化语言诸如c#、java等也都拥有该特性。
怎么理解这个概念呢? 先说说集合、超集、子集(set, superset, subset)
下图中有两个集合:脊索动物、哺乳动物。 哺乳动物一定是脊索动物,反之则不一定。 因此我们说脊索动物是哺乳动物的超集,哺乳动物是脊索动物的子集。
哺乳动物一定具有脊索动物的特性,反之则不一定。
协变
协变是指:子集能赋值给其超集。
class Chordate {
hasSpine(): boolean {
return true;
}
}
class Mammal extends Chordate {
canBreastFeed(): boolean {
return true;
}
}
function foo(animal: Chordate){
animal.hasSpine();
}
foo(new Chordate());
foo(new Mammal());
以上代码证明了Typescript支持协变,Mammal是Chordate的子集,方法foo接受参数类型为Chordate,而Mammal实例也能赋值给Chordate参数。
逆变
逆变(Contravariance)与双变(Bivariance)只针对函数有效。 --strictFunctionTypes 开启时只支持逆变,关闭时支持双变。
class Chordate {
hasSpine(): boolean {
return true;
}
}
class Mammal extends Chordate {
canBreastFeed(): boolean {
return true;
}
}
declare let f1: (x: Chordate) => void;
declare let f2: (x: Mammal) => void;
f2=f1;
f1=f2; //Error: Mammal is incompatible with Chordate
协变比较好理解,为什么函数赋值,只能支持逆变(默认),而不支持协变呢? 请看以下代码示例
class Animal {
doAnimalThing(): void {
console.log("I am a Animal!")
}
}
class Dog extends Animal {
doDogThing(): void {
console.log("I am a Dog!")
}
}
class Cat extends Animal {
doCatThing(): void {
console.log("I am a Cat!")
}
}
function makeAnimalAction(animalAction: (animal: Animal) => void) : void {
let cat: Cat = new Cat()
animalAction(cat)
}
function dogAction(dog: Dog) {
dog.doDogThing()
}
makeAnimalAction(dogAction) // TS Error at compilation, since we are trying to use `doDogThing()` to a `Cat`
上述代码说明了如果函数赋值支持协变的话,有可能会导致bug
参考:
https://codethrasher.com/post/2019-08-28-type-variance-and-typescript/
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html
https://dev.to/codeozz/how-i-understand-covariance-contravariance-in-typescript-2766
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具