[英]Difference between Variance, Covariance, Contravariance and Bivariance in TypeScript
Could you please explain using small and simple TypeScript examples what is Variance, Covariance, Contravariance and Bivariance?您能否使用小而简单的 TypeScript 示例解释什么是方差、协方差、逆变和双方差?
[CONTINUOUS UPDATE] [持续更新]
Useful links:有用的链接:
Another one good answer of Oleg Valter related to the topic Oleg Valter的另一个与该主题相关的好答案
Very good explanation of*-riance by Titian-Cernicova-Dragomir Titian-Cernicova-Dragomir对*-riance 的很好解释
Stephan Boyer blog 斯蒂芬博耶博客
Scala documentation - good explanation with examples Scala 文档- 用例子很好的解释
Mark Seemann 's article马克·西曼的文章
@jcalz explanation @jcalz 解释
Variance has to do with how a generic type F<T>
varies with respect to its type parameter T
.方差与泛型类型
F<T>
相对于其类型参数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.如果您知道
T extends U
,那么方差会告诉您是否可以得出结论F<T> extends F<U>
,得出结论F<U> extends F<T>
,或者两者都没有,或两者兼而有之。
Covariance means that F<T>
and T
co - vary .协方差意味着
F<T>
和T
协变。 That is, F<T>
varies with (in the same direction as) T
.也就是说,
F<T>
随T
变化(在相同的方向上)。 In other words, if T extends U
, then F<T> extends F<U>
.换句话说,如果
T extends U
,那么F<T> extends F<U>
。 Example:例子:
Function or method types co-vary with their return types: Function 或方法类型与其返回类型共同变化:
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:其他(暂时未说明)示例是:
Contravariance means that F<T>
and T
contra - vary .逆变意味着
F<T>
和T
反向变化。 That is, F<T>
varies counter to (in the opposite direction from) T
.也就是说,
F<T>
与T
逆向变化(在相反的方向上)。 In other words, if T extends U
, then F<U> extends F<T>
.换句话说,如果
T extends U
,那么F<U> extends F<T>
。 Example:例子:
Function types contra-vary with their parameter types (with --strictFunctionTypes
enabled): Function 类型与其参数类型相反(启用
--strictFunctionTypes
):
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:其他(暂时未说明)示例是:
Invariance means that F<T>
neither varies with nor against T
: F<T>
is neither covariant nor contravariant in T
.不变性意味着
F<T>
既不随 T 变化也不反对T
: F<T>
在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: Function 类型返回与其参数相同的类型,在该类型中既不协变也不反变:
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
.双变量意味着
F<T>
随 T和反T
变化: F<T>
在T
中既是协变的也不是逆变的。 In a sound type system, this essentially never happens for any non-trivial type function.在健全的类型系统中,这对于任何非平凡类型 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).您可以证明只有常量类型 function 像
type F<T> = string
是真正的双变量(快速草图: T extends unknown
对所有T
都是正确的,所以F<T> extends F<unknown>
和F<unknown> extends T
,并且在健全的类型系统中,如果A extends B
并且B extends B
,则A
与B
相同。因此,如果所有T
的F<T>
= F<unknown>
,则F<T>
是常数)。
But Typescript does not have nor does it intend to have a fully sound type system.但是 Typescript 没有也不打算拥有完全健全的类型系统。 And there is one notable case where TypeScript treats a type function as bivariant:
还有一个值得注意的情况是 TypeScript 将类型 function 视为双变量:
Method types both co-vary and contra-vary with their parameter types (this also happens with all function types with --strictFunctionTypes
disabled):方法类型与它们的参数类型共同变化和反向变化(这也发生在所有 function 类型禁用
--strictFunctionTypes
):
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 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.