现在,我正在使用Apollo Codegen生成的流类型。这是非常有用的工具,但是所有类型都是“也许”类型。现在,我遇到下一个问题:请考虑一个非常精简的示例(链接到Flow try):
/* @flow */
type Type1 = {| // <- example of Flow-type generated by Apollo Codegen
prop?: ?string
|}
type Type2 = { // <- example of my Flow-type
prop: string
}
function bar(y: Type2): void {
console.log(y.prop)
}
function foo(x: Type1): void {
if (x && x.prop && typeof x.prop === 'string') { // <- I'm trying to check the "x" argument
bar(x)
}
}
foo({ prop: 'hello' })
Flow无法理解我的检查,并由于null
或undefined
而显示错误。该如何管理?
答案 0 :(得分:2)
此操作无法进行类型优化的原因是您的检查可以同时通过Type1
和Type2
。 Flow执行条件检查,但检查可以通过Type1
的值,因此条件检查根本无法优化x
的类型。然后在条件中,您会看到您尝试将Type1
的值传递给Type2
。
要了解Flow的类型细化,请务必记住,除了变量的类型以外,Flow不会在该变量上携带其他细化数据。 Here是一个与您的示例相似的示例,但没有可选字段。在valid
函数中,我们检查y.field
的类型,然后在知道其类型后使用y.field
。在invalid
函数中,我们检查y.field
的类型,然后尝试使用y
。但是类型细化并没有改变y
的类型,仅改变了y.field
的类型,因此我们遇到了类型错误。
作为对点,here是一个示例,其中我们根据字段的值进行类型细化。需要注意的重要一点是,在f
函数内部,变量z
的类型为Baz | Qux
,而我们的优化是在两个字段之间不重叠的字段上进行的。在这种情况下,优化将类型Baz | Qux
转换为类型Baz
,我们可以正确地调用第二个函数。
要在您的情况下解决此限制,我们需要分解值x
,然后将要优化的字段放入其自己的变量中。然后,一旦我们知道该变量的类型,就创建一个我们知道类型为Type2
的值,并将其传递给所需的函数。 Here是最直接的方法。
因为这种事情经常发生,所以我有一种创建“转换”功能的模式,可以将可能不干净的数据转换为干净的数据,这样其他功能就不必烦恼细化的复杂性。在这种情况下,我会像this这样。
这种清除转换函数的模式在清理深度嵌套的数据或将嵌套的对象从类型mixed
转换为已知类型时也非常有用。通过合并小型类型的转换对象,为大型类型创建转换函数要比从头开始编写转换函数要容易得多。
答案 1 :(得分:0)
在此示例中,您要优化属性prop
的类型,而不是要优化x
。流的细化只能真正用于顶级类型。有关其他替代策略,请参见this question。