您能否使用小而简单的 TypeScript 示例来解释什么是方差、协方差、逆变和双方差?
[持续更新]
有用链接:
最佳答案
方差 与泛型类型的方式有关 F<T>
因类型参数而异 T
.如果你知道 T extends U
,那么方差将告诉您是否可以得出 F<T> extends F<U>
的结论, 得出结论 F<U> extends F<T>
,或两者都不是,或两者兼而有之。
协方差 意味着 F<T>
和 T
共变。即,F<T>
随(同方向)T
而变化.换句话说,如果 T extends U
,然后 F<T> extends F<U>
.例子:
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!
}
其他(暂时未说明)示例是:
逆变意味着
F<T>
和 T
相反。即,F<T>
与T
相反(相反方向)变化.换句话说,如果 T extends U
,然后 F<U> extends F<T>
.例子:--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
}
其他(暂时未说明)示例是:
不变性 意味着
F<T>
既不与也不反对 T
:F<T>
在 T
中既不协变也不逆变.这实际上是最一般情况下发生的情况。协变和逆变是“脆弱的”,因为当您组合协变和逆变类型函数时,很容易产生不变的结果。例子: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!
}
双方差意味着
F<T>
随和反对 T
:F<T>
在 T
中既是协变又是逆变.在健全的类型系统中,对于任何非平凡的类型函数,这基本上不会发生。您可以证明只有像 type F<T> = string
这样的常量类型函数是真正的双变(快速草图: T extends unknown
对所有 T
都是如此,所以 F<T> extends F<unknown>
和 F<unknown> extends T
,并且在声音类型系统中,如果 A extends B
和 B extends B
6 是相同的 | 6 A
。所以如果 B
= F<T>
对于所有 F<unknown>
,那么 T
是常数)。但是 Typescript 没有 nor does it intend to have一个完全健全的类型系统。还有one notable case其中 TypeScript 将类型函数视为双变量:
F<T>
的函数类型中):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 - TypeScript 中的方差、协方差、逆变和协方差的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66410115/