不精打细的流式转换,在对象(和所说对象的数组)中带有嵌套类型

时间:2019-03-23 14:04:43

标签: javascript flowtype

请考虑以下代码段,其中有两种对象类型。第二种是第一种的更完善的版本:

/* @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的精炼版本”。

2 个答案:

答案 0 :(得分:1)

文档Depth Subtyping页中的最后一段解释了这里发生的情况(文档当然有点烂)。

  

默认情况下,对象属性是不变的,它允许读写,但在接受的值上有更多限制。

现在,value的{​​{1}}属性默认是不变的。这意味着它 only 接受其给定类型,非常明确。您不能为其分配Anumber,而只能为其分配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的变量