New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flow——A static type checker for javascript #32

Open
qingying opened this Issue Dec 11, 2015 · 6 comments

Comments

Projects
None yet
6 participants
@qingying

qingying commented Dec 11, 2015

介绍

众所周知,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,则会报错。如图
img

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会报错,如图
img
这个时候需要我们在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

@myheartwillgoon

This comment has been minimized.

myheartwillgoon commented Dec 16, 2015

1+2不应该为13吧

@soulmachine

This comment has been minimized.

soulmachine commented Dec 20, 2015

有没有研究过怎么跟 webpack 集成呢?我搜索了一下,貌似大部分项目还是单独运行 flow check 命令来检查。目前找到的最方便的一个方法是使用这个 babel plugin babel-plugin-typecheck

@dd1994

This comment has been minimized.

dd1994 commented Dec 21, 2015

@soulmachine webpack 不是做这类事情的,它只是打包用的。运行任务的话就用 make 或者 gulp 之类的东西。

@xiaoqi1102

This comment has been minimized.

xiaoqi1102 commented Dec 24, 2015

@soulmachine @dd1994 webpack 确实有一个 flowcheck-loader 可以用的 https://www.npmjs.com/package/flowcheck-loader

@dd1994

This comment has been minimized.

dd1994 commented Dec 24, 2015

@xiaoqi1102 我只能说这个插件非常不科学,做了不应该做的事,所以 star 数这么少 🌚

@skyblue

This comment has been minimized.

skyblue commented Feb 26, 2016

我觉得在构建前跑flow挺合理的啊,类似eslint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment