
我们设计Flow的所有功能构建在现有Javascript规范之上。因为Flow主动地在后台工作,所以额外的编译开销很小。Flow并不要求开发者如何编写代码 —— 她用一套复杂的算法分析你熟悉的代码风格。
Flow仍然在初期阶段,但是我们已经在Facebook使用了。我们希望你在自己的项目中愉快的使用,期待你的反馈。可以访问 flowtype.org 快速开始。
总览
Facebook超爱Javascript;它快,表达性好,而且到处运行,是构建产品的极佳语言。同时,因为没有静态类型让开发者困扰。Bug难以发现(比如,崩溃的原因隐藏很深),代码维护犹如噩梦(比如,在不知道所有依赖的情况下进行重构风险很大)。Flow改进了速度和效率促进了开发者在使用Javascript的生成效率。
在Javascript之上添加一层静态系统并不简单。Javascript的积木(building block)表现力极高,一个简单的类型系统并不能精确组合出应有的语义。为了支持不同的Javascript编程范式和习惯,Flow引入了类似数据流(data-flow)和控制流(control-flow)这类通常用于编译时提取语义的分析技术。然后用提取的信息,加上先进的类型原理来做类型推断。当然,仅有一个强力的静态类型分析还不够 —— Javascript代码库会很大,这要求类型检查必须闪电般快速,才能不打断开发者编辑-运行的流程。Flow按模块执行分析,所有的类型都限制在模块边界以内。这最终形成一个高度并行、增量式的检查架构,类似 Hack 。这使得类型检查响应快速,即使是百万行级别代码。
Flow的类型检查是选择性的 —— 你不需要一次性执行检查所有。然而,Flow背后的设计基于假定大多数Javascript的代码类型是隐式静态类型;虽然类型可能不会到处在代码中出现,它们是以一种可以按照代码正确性推理出来的形式存在于开发者的思路中。一旦可能,Flow就去推断这些类型,意味着它可以不需要改动代码就能发现类型错误。另一发面,一些如存在于框架中的Javascript代码,大量使用了反射使得静态类型推断非常困难。对于这种天然动态的代码,类型检查就会错漏百出,因此Flow提供对此类代码添加信任并继续。这种设计在Facebook内部被大量的Javascript代码库所验证:大多数代码没有通过隐式静态类型检查条目,这些条目让开发者可以不用添加注释就能检查代码类型错误。
这使得Flow从根本上区别于其他Javascript的类型系统(如TypeScript),通过弱化的假设大多数JavaScript代码是动态输入的,并由开发者自己表达哪些代码应该是静态类型。通常来看,这类设计会导致检查覆盖率降低:更少的类型错误被检测到,工具不够高效。然而对于某些情况下是合理的,一般这种设计如果没有通过大量额外的努力就无法对实际开发提供足够多的帮助。尽管如此,Flow让你可以简单就获得这种弱化的类型检查,对于现有代码非常有用。
为了解释这种区别,请看下面的例子:
function onlyWorksOnNumbers(x) { return x * 10;}onlyWorksOnNumbers(‘Hello, world!");Flow能够发现这个错误(尝试把数字和字符串相乘),然而另一种更加保守的分析需要显式的标注 x 的类型。在这个玩具般的例子里面并不觉得费力,但是在巨型代码库里面几乎无人去做。Flow可以不用添加注释就能发现这个错误 —— 当然前提是开发者想这样做。function length(x) {return x.length;}var total = length("Hello") + length(null);Flow会在编译时期发现这个错误,并指出 x 可以是null( length 属性不应该被访问)。另外,Flow了解这个程序的控制流,所以简单修改就能让这个程序类型正确:function length(x) { if (x !== null) { return x.length; } else { return 0; }}var total = length("Hello") + length(null);Flow还了解JavaScript复杂的对象模型:构造器,方法,原型和它们动态扩展以及绑定。已经试验性去支持类型的复杂操作如:绑定对象,抽取keys等等。我们希望未来这些功能使得让为框架指定具体类型成为可能。var Hello = React.createClass ({ render: function() { return <div>Hello {this.props.name}</div>; }});如果你在JSX上使用的class名字有错误,Flow会发现这个问题:React.render(, ...);而且,如果你在React class里面使用了React.PropTypes规范,你可以对JSX上的attributes做静态类型检查:
var Hello = React.createClass ({ propTypes: { name: React.PropTypes.string.isRequired } ...});Flow就会发现 <Hello/> 缺少属性的错误,或者 <Hello name={42}/> 属性类型的错误。