Description
介绍
众所周知,javascript是一个动态类型语言,变量类型不需要声明,运算过程中会根据需要自动转换类型,这个是js的优点,够灵活,编码简单。但是同时也是软肋,相信很多人都会遇到这个问题,明明1+2我希望得到3,但是很多时候得到的却是13,什么时候number转成了string都不知道。相比一步一步查出哪里转的,这样写parseInt(1)+parseInt(2)或许更省力更有保障。
今天给大家介绍的flow则可以避免以上的问题。flow 是facebook团队出的一个js静态类型检测器,目的是通过最小的代码修改检测出代码中的类型问题。
安装
官网提供了众多安装方法,起初我觉得使用npm应该会是最便捷的。
npm install flow-bin —global
真的很慢,请耐心等待。
很慢之后还不一定会成功。
最后我这边实验出比较简单的方法,首先下载文件,然后在终端执行$PATH,找出环境变量路径,把下载的flow文件复制过去就行。
使用
在项目目录下执行 flow init,会生成一个.flowconfig文件
在需要检测的文件顶部增加注释
/* @flow */
执行flow check,检测你代码中是否有类型错误。
示例:
function simple(string){
return string.length;
}
simple(1);
示例中,想取传入参数的length属性,flow检测到传入值是一个number,不存在length,则会报错。如图
flow server
flow server是为了提高检测效率的后台程序,支持在后台运行,并且只监测有修改的文件。
flow:项目第一次执行或者.flowconfig有修改第一次执行的时候会比较慢,请耐心等下
flow:后面有修改之后执行能快速显示错误
flow stop:项目开发完成停止服务
flowconfig
- [ignore]忽略的文件,路径的匹配规则是正则表达式
- [include]需要检测的其他目录的文件
- [libs]当文件中有第三方库引用或者require全局的module时,需要在一个单独的文件里declare这个对象,这个的值是所有declare路径的集合
- [options]包含若干key-value的配置,详情见官方文档
libs示例
var React = require('react');
var com = React.create({
render: function(){
return (
<div className="page"></div>
)
}
})
示例中引用了react模块,没有带相对路径,flow找不到引用的地方。直接执行flow会报错,如图
这个时候需要我们在libs对应的目录下增加一个declare的文件,用了告诉flow我们这个引用的对象有哪些方法和熟悉
declare module react {
declare function create(): any;
}
变量赋值类型
除了通过变量的属性和方法来推断变量类型是否正确外,flow还支持通过在代码里增加类型声明,来达到更精准的错误提示。变量声明类型示例如下
class People {
name: string;
constructor(name:string){
this.name = name
}
getAge():number{
return 18;
}
}
function getLength(param?:string):number {
/*param?:string传参类型什么,?表示此处可不传值;*/
/*\:number为函数返回值类型,如果没有return可不写或写void*/
var s:string = 'string';/*字符*/
var ss:String = new String('string');/*字符对象*/
/* s = ss*///类型不同,flow会报错
var n:number = 12;/*数字*/
var nn:Number = new Number(12);/*数字对象*/
var b:boolean = true;/*bool值,仅能为true/false*/
var bb:Boolean = new Boolean(true);/*bool值对象*/
var o:{prop1:number,prop2:string} = {
/*对象熟悉声明*/
prop1: 12,
prop2: '21123'
}
var v:void = undefined;/*undefined*/
var a:any = 'aa';/*任意类型,除undefined*/
var m:mixed = '1';/*任意类型+undefined*/
var mm:mixed = undefined;/*任意类型+undefined*/
var aa:Array<number> = [1,2,3,4];/*数组内值类型声明*/
var P:Class<People> = People;/*自定义类型声明*/
var p:People = new People('pt');/*自定义People类型*/
if (param) {
return param.length;
} else {
return 0;
}
}
flow的两种模式
/@flow/ 只要带有这个注释,都会进行类型检测
/@flow weak/ 只对有加类型声明的变量进行类型检测
代码编译
增加类型声明的flow语法不是js的标准语法,这里需要使用babel来进行转换。目前可以选择使用的是babel的preset为react,或者babel的plugins为transform-flow-strip-types。不过在使用过程中发现class语法里react和flow同时解析会出现错误,所以为了保险起见最好先执行flow语法转换再做其他的语法转换。示例如下:
gulp.task('babel',['clean',],function(cb){
return gulp.src('src/*.js')
.pipe(
babel({
plugins: ["transform-flow-strip-types"]
})
)
.pipe(babel({
presets: ['react','es2015']
}))
.pipe(gulp.dest('build/'));
})
更多第一手资料,参见flow的官方文档
本文中提到的代码示例https://github.com/qingying/flow-demo