方差
与泛型类型的方式有关
F<T>
变化
关于其类型参数
T
如果你知道的话
T extends U
,那么方差将告诉你是否可以得出以下结论
F<T> extends F<U>
,得出以下结论
F<U> extends F<T>
或者两者都没有,或者两者都有。
协方差
意思是
F<T>
和
T
有限公司
-
变化
也就是说,
F<T>
随
(方向与)
T
换句话说,如果
T延伸U
那么
F<T>扩展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延伸U
那么
F<U>扩展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 A
那么
A
与
B
那么,如果
F<T>
=
F<unknown>
为所有人
T
那么
F<T>
恒定)。
但Typescript没有
nor does it intend to have
全声音型系统。还有
one notable case
其中TypeScript将类型函数视为双变量:
-
方法类型随其参数类型而变化(这也发生在所有具有
--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
}
Playground link to code