【问题标题】:How to make Flow understand dynamic code that uses lodash for runtime type-checking?如何让 Flow 理解使用 lodash 进行运行时类型检查的动态代码?
【发布时间】:2019-01-11 23:13:46
【问题描述】:

Flow 的 dynamic code example 表示 Flow 可以找出运行时类型检查:

function foo(x) {
  if (typeof x === 'string') {
    return x.length; // flow is smart enough to see this is safe
  } else {
    return x;
  }
}

var res = foo('Hello') + foo(42);

但在现实生活中,typeof 还不够好。我通常使用 lodash 的类型检查函数(_.isFunction_.isString 等),它们可以处理很多边缘情况。

问题是,如果我们将示例更改为使用 lodash 进行运行时类型检查,Flow 将不再理解它:

function foo(x) {
  if (_.isString(x)) {
    return x.length; // warning: `length` property not found in Number
  } else {
    return x;
  }
}

var res = foo('Hello') + foo(42);

我尝试使用iflow-lodash,但在这里似乎没有什么不同。

让 Flow 理解使用 lodash 进行运行时类型检查的代码的最佳解决方案是什么?顺便说一句,我是 Flow 新手。

【问题讨论】:

    标签: flowtype


    【解决方案1】:

    这取决于您的 lodash libdefs 中有谓词类型。

    谓词类型最近已添加到 Flow 中。虽然它们仍处于实验状态,但我建议您暂时谨慎使用它们。

    function isString(x): boolean %checks { // << declare that the method is a refinement
      return typeof x === 'string';
    }
    
    function method(x: string | number): number {
      if (isString(x)) { // << valid refinement
        return x.charCodeAt(0); // << no errors
      } else {
        return x;
      }
    }
    

    [try it out]

    注意:此答案可能会在下一个版本中很快过时,因为这是一项全新功能。查看 Flow 的changelog 了解最新信息。

    如果可能,目前的解决方案是使用the built-in refinements

    function method(x: string | number): number {
      if (typeof x === "string") { // << Inline the check
        return x.charCodeAt(0);
      } else {
        return x;
      }
    }
    

    【讨论】:

      【解决方案2】:

      针对这种特定情况最明显的解决方案是:

      if (_.isString(x) && typeof x === 'string') {
      

      一般来说,您可以通过创造性的错误抑制来克服 Flow 错误,如下所示:

      if (_.isString(x)) {
        // @ManuallyTyped
        var xStr: string = x;
        return xStr.length;
      } else { ... }
      

      确保在您的流程配置文件中将// @ManuallyTyped 定义为自定义suppress_comment 以使其正常工作。为此,您可能需要一个丑陋的正则表达式,请参阅流程文档。

      我上次这样做已经有一段时间了,但如果我没记错的话,Flow 会假设您的 xStrstring,而其余的类型检查将正常工作很好。

      【讨论】:

      猜你喜欢
      • 2020-07-13
      • 2016-07-15
      • 2020-10-20
      • 1970-01-01
      • 2014-06-02
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2017-10-09
      相关资源
      最近更新 更多