vue project configuration uses flow type checking

  Do you regularly debug easily avoidable bugs? Maybe you made a mistake in the order of the parameters when you passed the parameters to the function, or you should have passed a parameter of type Number, but you passed a type of String? JavaScript's weak typing is the culprit of this type of bug, which doesn't exist in statically typed languages. Flow is a static type checking tool for JavaScript. The goal of this library is to check type errors in JavaScript. Developers usually do not need to modify the code to use it, so the cost of use is very low. At the same time, it also provides additional syntax support, allowing developers to play the role of Flow to a greater extent.

1. Installation of flow

  flow can be installed directly via npm or yarn.

  Here is an example of npm: npm install --save-dev flow-bin

  After the installation is complete, add the following script to package.json

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

  At the same time, the babel compiler must be installed to strip the flow type checking code from the code and convert it into normal js code

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

  Add to the babel configuration file. babelrc

{
  "presets": ["flow"]
}

Second, flow use

1. Configure flow

  npm run flow initGenerate flow configuration file .flowconfig

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

[libs]

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

  [ignore]: Flow checks all files in the project directory by default, but there must be many files that we don't want to check, such as files in the node_modules, build and other directories, so we need to write these directories in the ignore configuration.

  [include]: The so-called project directory is actually the .flowconfig directory, not the real project directory. If we create a .flowconfig in a directory in this project, the directory where the .flowconfig is located will also become a Flow project . Then, if we want to check files or directories other than the current Flow project, we need to write them in the include configuration item.

  [libs]: In the project, we may use a lot of custom types, such as to record the structure of the object, it may be used in each file, we extract it as a global type or data structure , can be used in any file. For the convenience of management, we define the global types in one or more simple directories for unified management. There may be a defined data structure stored here, or it may be stored according to the data type corresponding to a class in the project. We write these files or directories in the libs configuration item, which is very important for us to use Flow.

  [options]: Fill in some configurations for the Flow project here. The configuration items are in the form of key=value, one per line. See the official documentation for all configurations

  [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文件。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324653582&siteId=291194637