在Flow中过滤Maybe(可空)类型数组以删除空值

Rob*_*rny 5 javascript functional-programming flowtype

我有一个Maybe(可空)类型的数组,我想过滤那些null有一个只包含非空值的数组:

@flow

type Foo = {
  foo: string
}

const bar: Array<?Foo> = [ null, { foo: 'Qux' } ]

const baz = bar
  .filter(x => x != null)
  .map(({ foo }) => foo);
Run Code Online (Sandbox Code Playgroud)

然而,流程抱怨论证仍然可以null,但显然不能:

11: .map(({ foo }) => foo);
            ^ property `foo`. Property cannot be accessed on possibly null value
Run Code Online (Sandbox Code Playgroud)

请参阅flow.org/try上的代码.

有没有办法告诉流量数组现在只包含不可为空的项目?

这破坏了我的函数式JavaScript编程.

Rob*_*rny 6

快速回答

使用.filter(Boolean)进行筛选null的。

const baz = bar
  .filter(Boolean) // <- This is the trick
  .map(({ foo }) => foo);
Run Code Online (Sandbox Code Playgroud)

检查它在flow.org/try传递

说明(某种)

流很难理解filter回调中发生了什么,如何获得结果以及是否真的null删除了所有值。因此,它假定过滤后数组的类型相同。实际上是正确的,它只能是数组的子集,因此也可以是类型的子集。

相反,由于它的工作方式,它reduce创建了一个完全不同的结构,必须为其推断类型(flow.org/try):

const baz = bar
  .reduce((prev, next) => next == null ? prev : [...prev, next], [])
  .map(({foo}) => foo);
Run Code Online (Sandbox Code Playgroud)

但是,这种用例非常普遍,流在其代码中包含一个异常:

filter(callbackfn: typeof Boolean): Array<$NonMaybeType<T>>;
filter(callbackfn: (value: T, index: number, array: $ReadOnlyArray<T>) => any, thisArg?: any): Array<T>;
Run Code Online (Sandbox Code Playgroud)

这意味着,如果(且仅当)Boolean作为回调传递,结果数组将具有type Array<$NonMaybeType<T>>Boolean一定会删除null(和undefined)并且可以信任。

  • 它适用于_this_情况,但它会删除所有“虚假”值。例如,与字符串数组相同的事情也会删除空字符串,甚至不尝试处理具有“未定义”值的布尔数组...:-) 确实很遗憾 Flow 甚至不理解简单的“===”(或“instanceof”)比较作为过滤函数。 (2认同)