如何让Flow理解使用lodash进行运行时类型检查的动态代码?

时间:2016-09-12 18:14:40

标签: flowtype

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 btw的新手。

2 个答案:

答案 0 :(得分:13)

这取决于你的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;
  }
}

答案 1 :(得分:0)

针对此特定案例的最明显的解决方案是:

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

通常,您可以通过创建性错误抑制来克服Flow错误,如下所示:

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

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

自从我上次这样做以来已经有一段时间了,但是如果我没记错的话Flow会假设你的xStrstring ,其余的类型检查工作正常。