请考虑以下代码段,其中有两种对象类型。第二种是第一种的更完善的版本:
/* @flow */
type A = {|
value: string | number,
|}
type B = {|
value: number,
|}
const b:B = { value: 2 };
const a:A = { value: 2 }; //works.
const z:A = b; //fails, but for javascript it is exactly the same as line above
这在最后一行失败,因为流程告诉我“数字”与“字符串”不兼容。但是类型是“联合”而不是交集,因此它应该工作吗? (只需再次使用该类型,就必须再次对其进行优化)。
在我的真实代码中,实际上我有所述对象的数组,并且对象包含更多数据,因此手动复制对象并不是路要走。
我意识到这是一个抽象的概述,但最后我希望有一个函数,该函数接受“精制A”并返回“ A”,即更真实的示例:
type A = {|
value: string | number,
value2: string,
|}
function foo(input: $ReadOnlyArray<{| ...$Exact<A>, value: number|}>): Array<A> {
return input.filter(v => v.value === 2);
}
有没有更好的说法:“此函数采用类型X的精炼版本”。
答案 0 :(得分:1)
文档Depth Subtyping页中的最后一段解释了这里发生的情况(文档当然有点烂)。
默认情况下,对象属性是不变的,它允许读写,但在接受的值上有更多限制。
现在,value
的{{1}}属性默认是不变的。这意味着它 only 接受其给定类型,非常明确。您不能为其分配A
或number
,而只能为其分配string
。具有给定类型且比number | string
更明确或更明确的任何内容将不被接受:
number | string
对此,我们可以做的一件事是将属性标记为协变,如同一段前面所述:
加号表示[...]属性是“协变量”。使用协变量属性使我们可以使用具有该属性的子类型兼容值的对象。
这应该使我们可以为我们的媒体资源分配更具体的类型(在这种情况下为type Ambiguous = {|
value: string | number,
|};
type Specific = {|
value: number,
|};
const myAmbiguous: Ambiguous = ({ value: 1 }: Specific); // error!
)
number
但是请注意,type Ambiguous = {|
+value: string | number,
|};
type Specific = {|
value: number,
|};
const myAmbiguous: Ambiguous = ({ value: 1 }: Specific); // all good
现在是只读的:
value
我建议通读该页面其余部分的深度子类型以及Type Variance上的页面。
答案 1 :(得分:0)
这是2种不同的类型,并且流程不允许分配。
您的2行不同 -第一个创建类型为A的对象并将其分配 -第二个对象希望将类型B的对象分配给类型A的变量