【问题标题】:Filtering an array of Maybe (nullable) types in Flow to remove null values在 Flow 中过滤可能(可为空)类型的数组以删除空值
【发布时间】:2017-05-23 17:55:09
【问题描述】:

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

@flow

type Foo = {
  foo: string
}

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

const baz = bar
  .filter(x => x != null)
  .map(({ foo }) => foo);

但是,flow 抱怨参数仍然可以是null,而它显然不能:

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

查看flow.org/try上的代码。

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

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

【问题讨论】:

    标签: javascript functional-programming flowtype


    【解决方案1】:

    快速解答

    使用.filter(Boolean) 过滤null

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

    检查它是否通过flow.org/try

    解释(有点)

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

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

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

    但是,这种用例非常常见,以至于流在its code 中包含一个异常:

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

    这意味着,当(且仅当)Boolean 作为回调传递时,结果数组的类型为Array&lt;$NonMaybeType&lt;T&gt;&gt;Boolean 肯定会删除 null(和 undefined)并且可以信任。

    【讨论】:

    • 它适用于 this 情况,但它会删除所有“虚假”值。例如,与字符串数组相同的东西也会删除空字符串,甚至不尝试处理具有undefined 值的布尔数组...... :-) 很遗憾 Flow 甚至不理解简单的===(或instanceof)比较作为过滤函数。
    • flow 无法在 array.filter 中推断出简单的 ===,这基本上使 flow 无法使用。强制使用不可读的array.reduce。如果我们必须这样做,为什么还要过滤?
    猜你喜欢
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多