vue 引入flow 静态类型检测器

2,753 阅读4分钟

一、背景

首先介绍一下什么是flow , 一个 JAVASCRIPT 静态类型检测器 为什么js 要进行类型检测? 对于javasscrip 来说,JavaScript 是一种弱类型(或称动态类型)语言,即变量的类型是不确定的。

x = 5; // 5
x = x + 'A'; // '5A'

优点-灵活,代码简洁 缺点-不利于发现类型错误,存在数据隐患,经常会遭到接触过后端语言同学的吐槽

二、目前转化成强类型的方法

  1. TypeScript 是微软2012年推出的一种编程语言,属于 JavaScript 的超集,可以编译为 JavaScript 执行 为什么没有采用TypeScript 的方式,主要有以下几方面考虑
  • 虽然语法与javascript有很多相似的地方,但是总归是一门新的语言类型,相对来说有一定的学习成本
  • 项目比较成熟,javascript 迁移TypeScript 相对工作量以及改动比较大
  • 虽然vue2.0 已经支持了TypeScript的方式,但是不能保证我们应用的所有的组件库都对此语法支持,为避免后期又不确定的麻烦
  1. Flow 是 Facebook 在2014年发布的一个类型检查工具
  • 安装简单
  • 相对没有学习成本
  • 对已经成熟的项目改动较小
  • 支持eslint 检测
  • vue 源码采用的Flow 类型检测的方式

三、flow 的引入

1. 安装包

yarn add flow-bin @babel/preset-flow -D

2. 生成flow 文件

flow init 会生成一个.flowconfig 文件,修改文件配置

 [ignore]
 .*/node_modules/.*
 .*/test/.*
 .*/build/.*
 .*/config/.*
 [include]
 
 [libs]
 
 [options]
 module.file_ext=.vue
 module.file_ext=.js

3. 执行flow

在文件头部写入/* @flow */ 或者 // @flow 弱模式: /* @flow weak */ ,在弱模式下,Flow 就不做那么多类型检测, 对方法内的类型还是会探测,但是对其他未注解的变量,会认为他们可以是 any 任何类型——也就意味着无须检测,适合项目初期 然后运行 flow check 或者 yarn run flow 我们会看到文件报错信息,表明项目已经安装flow 成功

但是每次都手动执行命令检查很麻烦,所以下面我们配置自动检查

4. 修改babel

修改.babel/babel.config.js 文件,添加@babel/preset-flow,这样babel 在编译的时候会移除 Flow 注解,把添加类型检测的文件转化成浏览器可支持的语法

  presets: [
   '@babel/preset-flow'
   ]

5. 添加eslint 代码检测 eslint-plugin-flowtype

yarn add eslint-plugin-flowtype -D 修改.eslintrc.js 文件

extends: [
    'plugin:flowtype/recommended',
  ],
rules: [
  'flowtype/require-parameter-type': 2,
  'flowtype/generic-spacing': 2
},
....
  plugins: ['flowtype'],
  settings: {
    flowtype: {
      onlyFilesWithFlowAnnotation: true //只在添加@flow注释的文件才做检查
    }
  }

四、flow 使用方式简介

1. 类型注释 / 类型注解

在大多数情况下,Flow 都能够探测出具体类型,所以你不需要给每个方法、变量都添加类型注解。 虽说 Flow 能探测出类型,但是你依然可以严格声明类型。 只有下面这类情况才 必须 明确地声明类型:变量/方法/类 是从别的模块中导入的(在别的文件定义)

// @flow

(function() { 
function foo(x: string, y: number): string {
  return x.length * y;
}

foo('Hello', 42);
}); 

这表示 foo 方法返回值的类型为 string,并且两个参数类型分别为 string 和 number

2. 原生数据类型

boolean、number、string、null、void 此处需要注意 上面的类型属性 与 Number, String, Boolean是有本质的区别的,我们通过代码来看一下 代码类型为小写,表示常规类型

// @flow
function method(x: number, y: string, z: boolean) {
  // ...
}

method(3.14, "hello", true);

代码类型为大写,表示对象类型

// @flow
function method(x: Number, y: String, z: Boolean) {
  // ...
}

method(new Number(42), new String("world"), new Boolean(false));

3. 未确定类型(Maybe types)

我们可以使用type 用 ?type, 表示此类型可能为type 类型,也有可能是 null or void.

// @flow
function acceptsMaybeString(value: ?string) {
  // ...
}

acceptsMaybeString("bar");     // Works!
acceptsMaybeString(undefined); // Works!
acceptsMaybeString(null);      // Works!
acceptsMaybeString();   

如果是对象类型的,我们可以使用 { propertyName?: string }

4. 泛型

泛型对象可以使用别名类型来定义

type GenericObject<T> = { foo: T };
var numberObject: GenericObject<number> = { foo: 0 };
var stringObject: GenericObject<string> = { foo: "foo" };

这里只介绍常规的使用方法以及 API ,详细内容还需要大家看文档

五、报错处理

1. types' can only be used in a .ts file

如果使用的vscode 我们在只从过程中可能会遇到 此问题, 解决办法: 关闭vs code 的检测
"javascript.validate.enable": false

六、参考文章