@Titian 的答案 2Vlad Riscutia 的博客Mark Seemann 的文章> 解决方案 Variance 与泛型类型 F<T> varies 的变化有关em> 关于它的类型参数 T.如果您知道 T 扩展 U,那么方差将告诉您是否可以得出 F 的结论.扩展 F,得出 F;扩展 F<T>,或者两者都不扩展,或者两者都扩展.Covariance 表示 F 和 T co-vary.也就是说,F 随变化(与T同向).换句话说,如果 T 扩展 U,则 F;扩展 F.示例:函数或方法类型与其返回类型共同变化:类型 Co= () =>Ⅴ;函数协方差(t:T,u:U,coT:Co T ,coU:Co U ){u = t;//好的t = u;//错误!coU = coT;//好的coT = coU;//错误!}其他(暂时未说明)示例是:对象在它们的属性类型上是协变的,即使这对于可变属性来说不合理类构造函数的实例类型是协变的逆变意味着F和T相反-变化.也就是说,F 与相反(与T相反).换句话说,如果 T 扩展 U,则 F扩展 F.示例:函数类型与其参数类型相反(使用 --strictFunctionTypes 已启用):type Contra= (v: V) =>空白;函数逆变(t:T,u:U,contraT:Contra,contraU:Contra){u = t;//好的t = u;//错误!contraU = contraT;//错误!contraT = contraU;//好的}其他(暂时未说明)示例是:对象的键类型是逆变的类构造函数的构造参数类型是逆变的Invariance 意味着 F 既不随 T 变化也不随 T 变化:F 是T 中既不协变也不逆变.这实际上是最一般情况下发生的情况.协方差和逆变是脆弱的"因为当你结合协变和逆变类型函数时,很容易产生不变的结果.示例:返回与其参数相同类型的函数类型在该类型中既不共变也不反变:输入= (v: V) =>Ⅴ;函数不变性(t:T,u:U,inT:In,inU:In){u = t;//好的t = u;//错误!inU = inT;//错误!inT = inU;//错误!}Bivariance 意味着 F both 与 和 相对于 T 变化>: F 在 T 中既是协变又是逆变.在健全的类型系统中,对于任何非平凡的类型函数,这基本上永远不会发生.您可以证明只有像 type F<T> 这样的常量类型函数才可以.= string 确实是双变的(速写:T extends unknown 对所有 T 都是正确的,所以 F extends F 和 F extends T,在声音类型系统中,如果 A extends B 和 B extends B,则 A 与 B 相同.所以如果 F = F 对于所有 T,则 F 是常数).但是 Typescript 没有 它也不打算有 一个完全健全的类型系统.还有一个一个值得注意的案例,其中TypeScript对待作为双变量的类型函数:方法类型与其参数类型同时变化和相反(这也发生在所有禁用 --strictFunctionTypes 的函数类型中):type Bi= { foo(v: V): void };函数双方差<U,T扩展U>(t:T,u:U,biT:Bi T ,biU:Bi U ){u = t;//好的t = u;//错误!双 = 比特;//好的双 = 双;//好的} 游乐场代码链接Could you please explain using small and simple TypeScript examples what is Variance, Covariance, Contravariance and Bivariance?[CONTINUOUS UPDATE]Useful links:Another one good answer of Oleg Valter related to the topicVery good explanation of*-riance by Titian-Cernicova-DragomirStephan Boyer blogScala documentation - good explanation with examples@Titian's answer 1@Titian's answer 2Vlad Riscutia 's blogMark Seemann 's article 解决方案 Variance has to do with how a generic type F<T> varies with respect to its type parameter T. If you know that T extends U, then variance will tell you whether you can conclude that F<T> extends F<U>, conclude that F<U> extends F<T>, or neither, or both.Covariance means that F<T> and T co-vary. That is, F<T> varies with (in the same direction as) T. In other words, if T extends U, then F<T> extends F<U>. Example:Function or method types co-vary with their return types:type Co<V> = () => V;function covariance<U, T extends U>(t: T, u: U, coT: Co<T>, coU: Co<U>) { u = t; // okay t = u; // error! coU = coT; // okay coT = coU; // error!}Other (un-illustrated for now) examples are:objects are covariant in their property types, even though this not sound for mutable propertiesclass constructors are covariant in their instance typesContravariance means that F<T> and T contra-vary. That is, F<T> varies counter to (in the opposite direction from) T. In other words, if T extends U, then F<U> extends F<T>. Example:Function types contra-vary with their parameter types (with --strictFunctionTypes enabled):type Contra<V> = (v: V) => void;function contravariance<U, T extends U>(t: T, u: U, contraT: Contra<T>, contraU: Contra<U>) { u = t; // okay t = u; // error! contraU = contraT; // error! contraT = contraU; // okay}Other (un-illustrated for now) examples are:objects are contravariant in their key typesclass constructors are contravariant in their construct parameter typesInvariance means that F<T> neither varies with nor against T: F<T> is neither covariant nor contravariant in T. This is actually what happens in the most general case. Covariance and contravariance are "fragile" in that when you combine covariant and contravariant type functions, its easy to produce invariant results. Example:Function types that return the same type as their parameter neither co-vary nor contra-vary in that type:type In<V> = (v: V) => V;function invariance<U, T extends U>(t: T, u: U, inT: In<T>, inU: In<U>) { u = t; // okay t = u; // error! inU = inT; // error! inT = inU; // error!}Bivariance means that F<T> varies both with and against T: F<T> is both covariant nor contravariant in T. In a sound type system, this essentially never happens for any non-trivial type function. You can demonstrate that only a constant type function like type F<T> = string is truly bivariant (quick sketch: T extends unknown is true for all T, so F<T> extends F<unknown> and F<unknown> extends T, and in a sound type system if A extends B and B extends B, then A is the same as B. So if F<T> = F<unknown> for all T, then F<T> is constant).But Typescript does not have nor does it intend to have a fully sound type system. And there is one notable case where TypeScript treats a type function as bivariant:Method types both co-vary and contra-vary with their parameter types (this also happens with all function types with --strictFunctionTypes disabled):type Bi<V> = { foo(v: V): void };function bivariance<U, T extends U>(t: T, u: U, biT: Bi<T>, biU: Bi<U>) { u = t; // okay t = u; // error! biU = biT; // okay biT = biU; // okay}Playground link to code 这篇关于TypeScript 中的方差、协方差、逆变和双方差的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!