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

cal*_*lum 4 flowtype

Flow的动态代码示例表明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);
Run Code Online (Sandbox Code Playgroud)

但在现实生活中,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);
Run Code Online (Sandbox Code Playgroud)

我尝试使用iflow-lodash,但这似乎没有什么区别.

什么是让Flow理解使用lodash进行运行时类型检查的代码的最佳解决方案?我是Flow Btw的新手.

Jam*_*yle 14

这取决于你的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;
  }
}
Run Code Online (Sandbox Code Playgroud)

[ 尝试一下 ]

注意:由于这是一个全新的功能,因此在下一个版本中,此答案很快就会过时.查看Flow的更新日志以获取最新信息.

如果可能,现在的解决方案是使用内置的改进.

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