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 相关文章推荐
node.js实现多图片上传实例
Jun 03 Javascript
JavaScript 变量、作用域及内存
Apr 08 Javascript
JS判断浏览器是否安装flash插件的简单方法
Sep 13 Javascript
EditPlus中的正则表达式 实战(2)
Dec 15 Javascript
关于Javascript中document.cookie的使用
Mar 08 Javascript
angularjs中的$eval方法详解
Apr 24 Javascript
swiper动态改变滑动内容的实现方法
Jan 17 Javascript
react native 原生模块桥接的简单说明小结
Feb 26 Javascript
详解小程序之简单登录注册表单验证
May 13 Javascript
vue动态禁用控件绑定disable的例子
Oct 28 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
Mar 25 Javascript
JS创建或填充任意长度数组的小技巧汇总
Oct 24 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
php数组的一些常见操作汇总
2011/07/17 PHP
PHP扩展框架之Yaf框架的安装与使用
2016/05/18 PHP
支持汉转拼和拼音分词的PHP中文工具类ChineseUtil
2018/02/23 PHP
JAVASCRIPT HashTable
2007/01/22 Javascript
12个非常有创意的JavaScript小游戏
2010/03/18 Javascript
js实现单一html页面两套css切换代码
2013/04/11 Javascript
判断滚动条到底部的JS代码
2013/11/04 Javascript
js读取配置文件自写
2014/02/11 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
jquery实现倒计时功能
2015/12/28 Javascript
JavaScript数据结构链表知识详解
2016/11/21 Javascript
ES6新特性七:数组的扩充详解
2017/04/21 Javascript
Vue的Class与Style绑定的方法
2017/09/01 Javascript
微信小程序中吸底按钮适配iPhone X方案
2017/11/29 Javascript
Vue引入jquery实现平滑滚动到指定位置
2018/05/09 jQuery
使用Node搭建reactSSR服务端渲染架构
2018/08/30 Javascript
微信小程序图片左右摆动效果详解
2019/07/13 Javascript
解决vue项目中遇到 Cannot find module ‘chalk‘ 报错的问题
2020/11/05 Javascript
[03:28]2014DOTA2国际邀请赛 走近EG战队天才中单Arteezy
2014/07/12 DOTA
Python中pygame的mouse鼠标事件用法实例
2015/11/11 Python
python浪漫表白源码
2019/04/05 Python
PyCharm2018 安装及破解方法实现步骤
2019/09/09 Python
python随机生成库faker库api实例详解
2019/11/28 Python
python如何运行js语句
2020/09/09 Python
如何利用python正则表达式匹配版本信息
2020/12/09 Python
Python datetime模块的使用示例
2021/02/02 Python
Python使用Turtle模块绘制国旗的方法示例
2021/02/28 Python
TripAdvisor土耳其网站:全球知名旅行社区,真实旅客评论
2017/04/17 全球购物
新加坡领先的在线生活方式和杂货购物网站:EAMART
2019/04/02 全球购物
学生自我鉴定模板
2013/12/30 职场文书
养殖行业的创业计划书
2014/01/05 职场文书
幼儿园小班教学反思
2014/02/02 职场文书
我的中国梦演讲稿300字
2014/08/19 职场文书
超市督导岗位职责
2015/04/10 职场文书
win11无线投屏在哪设置? win11无线投屏功能的使用方法
2022/04/08 数码科技