vue项目配置使用flow类型检查的步骤


Posted in Javascript onMarch 18, 2020

你是否经常在debug那些简单可避免的bug?可能你给函数传参的时候搞错了参数的顺序,或者本来应该传个Number类型的参数,你传了一个String类型?JavaScript的弱类型是这一类bug的罪魁祸首,静态类型语言中不存在此类bug。Flow就是JavaScript的静态类型检查工具,该库的目标在于检查JavaScript中的类型错误,开发者通常不需要修改代码即可使用,故使用成本很低。同时,它也提供额外语法支持,使得开发者能更大程度地发挥Flow的作用。

一、flow的安装

flow可以直接通过npm或者yarn安装。

这里以npm为例:npm install --save-dev flow-bin

安装完成后在package.json中加入下面的脚本

"scripts": {
  "flow":"flow check"
 }

同时还要安装babel编译器,将flow的类型检查代码从代码中剥离,转变成正常的js代码

npm install --save-dev babel-cli babel-preset-flow

在babel配置文件.babelrc中加入

{
 "presets": ["flow"]
}

二、flow使用

1、配置flow

npm run flow init生成flow配置文件.flowconfig

[ignore]
.*/node_modules/.*
.*/test/.*
.*/build/.*
.*/config/.*
[include]

[libs]

[options]
module.file_ext=.vue 
module.file_ext=.js

[ignore]:Flow 默认检查项目目录下所有文件,但是有很多文件必定是我们不想检查的,就像 node_modules、build 等目录下的文件,所以我们需要在将这些目录写在 ignore 配置下。

[include]:所谓的项目目录其实是 .flowconfig 目录,并不是真正的项目目录,如果我们在这个项目中的某个目录下创建一个 .flowconfig,那么 .flowconfig 所在的目录也会变为一个 Flow 项目。那么,如果我们想对当前 Flow 项目以外的文件或者目录进行检查,需要把它们写在 include 配置项中。

[libs]:在项目中,我们可能会用到很多自定义的类型,比如说要记录对象的结构,它可能在每个文件中都会被运用到,我们将其抽取为全局的类型或数据结构,在任何文件都可以使用。为了管理方便,我们将全局类型都定义在一个或多个单纯的目录中统一管理。这里存放的有可能是一个定义好的数据结构,存放的也有可能是根据项目中某个类对应的数据类型。我们将这些文件或目录写在 libs 配置项中,这个配置对于我们使用 Flow 来说很重要。

[options]:这里填写对 Flow 项目的一些配置,配置项以key=value的形式,每行写一个。所有的配置见官方文档

[lints]:官网中没有提到 lints 相关的配置

2、新建一个文件index.js

// @flow 
let a:number = '3';
// @flow或者 /* @flow */,告诉flow检查这个文件

如果不愿意那么麻烦,想检查全部文件,那么可以修改配置文件.flowconfig,在[options]配置项中添加 all=ture。

[ignore]
[include]
[libs]
[options]
all=true
[lints]

[libs] 配置项中的文件不需要添加// @flow,它们都将被检查。

注:在vue单文件组件使用flow需要额外配置:

(1)在.flowconfig文件的[options]中配置.vue文件扩展名,module.file_ext=.vue

(2)在.vue文件中需注释掉template script styled标签

输入npm run flow 执行类型检查。

注:完成设置之后,在终端输入以下命令可以在你的项目根目录以及任何子目录文件夹下进行专门的类型检查:npm run flow check,但是,这并不是最高效的使用方式,因为每次Flow都会重新检查整个项目的所有文件。开发过程中,推荐启动Flow服务:Flow服务的工作方式是增量检查,也就是说它只检查变化的部分。在终端输入以下命令来启动Flow服务:npm run flow,首次运行该命令时,服务启动并且显示最初类型检查结果。这保证了Flow更高效的增量式工作流。然后接下来每次想要知道检测结果,只要输入flow命令即可。开发结束之后,输入npm run flow stop停止服务。

Flow的类型检查是可选的,并不需要一次性检查所有代码。你可以选择你想要检查的文件,只要在对应的JavaScript文件最前面加上带有@flow标识的注释即可:/*@flow*/,当你想在已有项目中加入Flow的时候,该特性特别有帮助。因为你可以一一选择并检测你要的文件,然后修正错误。

三、类型推断

通常,类型检查分为以下两种方式:

通过注释:事先注释好我们期待的类型,Flow就会基于这些注释来评估

通过代码推断:通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型

第一种方式,我们需要额外编写只在开发阶段起作用的代码,最后在代码编译打包的阶段被剔除。显然,这种额外添加类型注释的方式增加了工作量。

第二种方式,不需要任何代码修改即可进行类型检查,最小化开发者的工作量。它不会强制你改变开发习惯,因为它会自动推断出变量的类型。这就是所谓的类型推断,Flow最重要的特性之一。

我们来通过一个例子来说明这个特性:

/*@flow*/
function foo(x) {
 return x.split(' ');
}

foo(34);

当你在终端运行npm run flow命令的时候,上述代码会报错,因为函数foo()的期待参数是字符串,而我们输入了数字。错误信息类似如下:

index.js:4
  4:   return x.split(' ');
                ^^^^^ property `split`. Property not found in
  4:   return x.split(' ');
              ^ Number

上述信息清楚地指出了出错位置和错误原因。我们只要将参数变成字符串,即可修正错误。该例想说明的是,因为split()方法只适用于string类型的变量,所以x应该是string,这就是类型推断。

四、空类型

Flow处理null的方式与其他类型库不同。它不会忽略null,这样可以防止了因给变量传了null而导致程序崩溃的错误。

/*@flow*/
function stringLength (str) {
 return str.length;
}
var length = stringLength(null);
Flow会报错。为了防止出错,我们需要单独处理null。


/*@flow*/
function stringLength (str) {
 if (str !== null) {
  return str.length;
 }
 return 0;
}
var length = stringLength(null);

代码中我们引入对null的检查,确保代码能在任何情况下都正常且正确运行。上述代码可以通过Flow的类型检查。

五、类型注释

如上所述,类型推断是Flow最有用的特性之一,不需要编写类型注释就能获取有用的反馈。但在某些特定的场景下,添加类型注释可以提供更好更明确的检查依据。考虑以下代码:

/*@flow*/
function foo(x, y){
 return x + y;
}
foo('Hello', 42);

Flow检查上述代码时检查不出任何错误,因为+即可以用在字符串上,也可以用在数字上,我们并没有明确指出add()的参数必须为数字。

在这种情况下,我们可以借助类型注释来指明期望的类型。类型注释是以冒号:开头,可以在函数参数,返回值,变量声明中使用。如果我们在上段代码中添加类型注释,就会变成如下:

/*@flow*/
function foo(x : number, y : number) : number {
 return x + y;
}
foo('Hello', 42);

现在Flow就能检查出错误,因为函数参数的期待类型为数字,而我们提供了字符串。Flow报错信息类似如下:

index.js:7
  7: foo('Hello', 42);
         ^^^^^^^ string. This type is incompatible with the expected param type of
  3: function foo(x : number, y : number) : number{
                      ^^^^^^ number

如果传入的参数是数字,就不会有错误。类型注释在大型复杂的JavaScript文件中也很有用,它能保证代码按照预期进行。

六、Flow能支持的其他更多类型注释。

其实说到底就是类似java那种强语言类型的写法,给每个变量声明是什么类型,给每个函数声明返回值类型,给每个数组元素声明类型等,就是仿造java的写法,哈哈,java传值不对时就会给你报错一样的道理

1、函数

/*@flow*/
function add(x : number, y : number) : number {
 return x + y;
}
add(3, 4);

上述代码展示了变量类型注释以及函数类型注释。函数add()的参数,以及函数的返回值,期待类型为数字。如果传入其他类型参数,Flow就会检测到错误。

2、数组

var foo : Array<number> = [1,2,3];

数组类型注释的格式是Array<T>,T表示数组中每项的数据类型。在上述代码中,foo是每项均为数字的数组。

3、类

下面展示了类和对象的类型注释模型。唯一需要注意的是,可以在两个类型之间使用或逻辑,用|来间隔。变量bar1添加了必须为Bar类的类型注释。

class Bar{
 x:string;      // x should be string    
 y:string | number; // y can be either a string or a number
 constructor(x,y){
  this.x=x;
  this.y=y;
 }
}

var bar1 : Bar = new Bar("hello",4);

4、对象字面量

对象的类型注释类似于类,指定对象属性的类型。

var obj : {a : string, b : number, c: Array<string>, d : Bar} = {
 a : "hello",
 b : 42,
 c : ["hello", "world"],
 d : new Bar("hello",3)
}

5、Null

若想任意类型,T可以为null或者undefined,只需类似如下写成 ?T 的格式即可。

/*@flow*/
var foo : ?string = null;

此时,foo可以为字符串,也可以为null。

目前我们只对Flow的类型注释做了很浅的探索。一旦你习惯了使用这些基本类型,建议在Flow官网上的类型文档深入了解所有的类型。

七、库定义

我们经常需要引入第三方库,Flow检查时就会抛出错误。但这并不是我们期待的错误。

庆幸的是,我们不需要修改库源码去防止这些报错。我们只需创建一个库定义(libdef)。libdef是包含第三方库声明的JS文件简称。观察下面的例子:

/* @flow */
var users = [
 { name: 'John', designation: 'developer' },
 { name: 'Doe', designation: 'designer' }
];

function getDeveloper() {
 return _.findWhere(users, {designation: 'developer'});
}

Flow会检查出以下错误:

interfaces/app.js:9
  9:   return _.findWhere(users, {designation: 'developer'});
              ^ identifier `_`. Could not resolve name

由于Flow并不认识_,所以会报错。要解决这个问题,我们需要引入Underscore的库定义

1、使用flow-typed

flow-typed仓库包含了众多流行的第三方库的libdef。只需在项目根目录下创建一个名为flow-typed的文件夹,并且下载相关的定义文件即可。为了进一步简化,可以用npm的命令行方式一键获取和安装libdef文件:npm install -g flow-typed

安装成功之后, 运行flow-typed install来检查package.json文件,并且下载所有项目中用到的第三方库的libdef。

2、自定义libdef

如果你用的库并不在flow-typed仓库,你可以创建你自己的libdef。本文不会细谈自定义libdef,因为很少会有人遇到,感兴趣可以查看此文档。

八、剔除类型注释

由于额外添加的类型注释不是正确的JavaScript语法,打包编译的时候需要在源码中剔除。可以通过flow-remove-types来剔除,或者如果你已经用Babel来转译JS,你可以使用Babel preset来移除。我们只讨论第一种方法。

首先需要安装flow-remove-types作为项目依赖库:npm install --save-dev flow-remove-types

然后在package.json文件中添加另一个script入口:

"scripts": {
 "flow": "flow",
 "build": "flow-remove-types src/ -D dest/",
}

上述命令将剔除src文件夹下的所有类型注释,在dist文件夹中保存编译后的版本。编译后的文件就是普通的能运行于浏览器的JavaScript文件。

到此这篇关于vue项目配置使用flow类型检查的步骤的文章就介绍到这了,更多相关vue flow类型检查内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
window.onbeforeunload方法在IE下无法正常工作的解决办法
Jan 23 Javascript
JavaScript 内置对象属性及方法集合
Jul 04 Javascript
JQuery学习笔记 nt-child的使用
Jan 17 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
Jun 18 Javascript
JS保留小数点(四舍五入、四舍六入)实现思路及实例
Apr 25 Javascript
IE下window.onresize 多次调用与死循环bug处理方法介绍
Nov 12 Javascript
JS显示日历和天气的方法
Mar 01 Javascript
js实现统计字符串中特定字符出现个数的方法
Aug 02 Javascript
jQuery实现花式轮播之圣诞节礼物传送效果
Dec 25 Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
Jul 07 Javascript
Angularjs过滤器实现动态搜索与排序功能示例
Dec 13 Javascript
JavaScript arguments.callee作用及替换方案详解
Sep 02 Javascript
Vue项目中使用flow做类型检测的方法
Mar 18 #Javascript
JavaScript正则表达式验证登录实例
Mar 18 #Javascript
JS正则表达式验证密码强度
Mar 18 #Javascript
原生js实现密码强度验证功能
Mar 18 #Javascript
JavaScript实现密码强度实时验证
Mar 18 #Javascript
js如何验证密码强度
Mar 18 #Javascript
js验证密码强度解析
Mar 18 #Javascript
You might like
详解ThinkPHP3.2.3验证码显示、刷新、校验
2016/12/29 PHP
php将html转为图片的实现方法
2017/05/19 PHP
有一段有意思的代码-javascript现实多行信息
2007/08/26 Javascript
JAVASCRIPT车架号识别/验证函数代码 汽车车架号验证程序
2012/01/08 Javascript
浅析Node.js查找字符串功能
2014/09/03 Javascript
使用JavaScript获取地址栏参数的方法
2014/12/19 Javascript
jquery实现点击展开列表同时隐藏其他列表
2015/08/10 Javascript
关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
2016/06/30 Javascript
什么是JavaScript注入攻击?
2016/09/14 Javascript
JavaScript中绑定事件的三种方式及去除绑定
2016/11/05 Javascript
JavaScript运动框架 多物体任意值运动(三)
2017/05/17 Javascript
vue bootstrap小例子一枚
2017/06/09 Javascript
解决IE11 vue +webpack 项目中数据更新后页面没有刷新的问题
2018/09/25 Javascript
100行代码实现一个vue分页组功能
2018/11/06 Javascript
新手快速入门JavaScript装饰者模式与AOP
2019/06/24 Javascript
JavaScript判断数据类型有几种方法及区别介绍
2020/09/02 Javascript
[01:10:02]IG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
在Python中操作字典之update()方法的使用
2015/05/22 Python
Python与Java间Socket通信实例代码
2017/03/06 Python
Django实现自定义404,500页面教程
2017/03/26 Python
详解Python中for循环是如何工作的
2017/06/30 Python
Python实现导出数据生成excel报表的方法示例
2017/07/12 Python
解决Scrapy安装错误:Microsoft Visual C++ 14.0 is required...
2017/10/01 Python
python使用Plotly绘图工具绘制散点图、线形图
2019/04/02 Python
Python telnet登陆功能实现代码
2020/04/16 Python
matplotlib.pyplot.plot()参数使用详解
2020/07/28 Python
html5 canvas实现圆形时钟代码分享
2013/12/25 HTML / CSS
台湾流行服饰购物平台:OB严选
2018/01/21 全球购物
解释i节点在文件系统中的作用
2013/11/26 面试题
初中三年学生的学习自我评价
2013/11/13 职场文书
办公室内勤工作职责
2013/12/11 职场文书
小学教育见习总结
2015/06/23 职场文书
幼儿园开学报名通知
2015/07/16 职场文书
2019入党申请书范文3篇
2019/08/21 职场文书
基于JavaScript实现年月日三级联动
2021/06/22 Javascript
CSS中妙用 drop-shadow 实现线条光影效果
2021/11/11 HTML / CSS