是什么?
Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码
https://flow.org/en/docs/getting-started/
-
关于vue2的版本,在 vue@2.6.14 都在使用,在 vue@2.7.0 开始向vue3版本靠了,都不用一套构建流程了
-
它与Typescript不同的是,它可以部分引入,不需要完全重构整个项目,所以对于一个已有一定规模的项目来说,迁移成本更小,也更加可行。除此之外,Flow可以提供实时增量的反馈,通过运行Flow server不需要在每次更改项目的时候完全从头运行类型检查,提高运行效率
安装使用flow
安装babel
npm install --save-dev @babel/core @babel/cli @babel/preset-flow babel-plugin-syntax-hermes-parser
创建.babelrc文件
{
"presets": ["@babel/preset-flow"],
"plugins": ["babel-plugin-syntax-hermes-parser"],
}
安装flow-bin
npm install --save-dev flow-bin
在package.json中添加script
{
"name": "my-flow-project",
"version": "1.0.0",
"devDependencies": {
"flow-bin": "^0.241.0"
},
"scripts": {
"flow": "flow"
}
}
初始化配置
https://flow.org/en/docs/config/
运行命令
npm run flow init
得到.flowconfig配置文件
[ignore]
.*/node_modules/.*
.*/test/.*
.*/build/.*
.*/config/.*
[include]
[libs]
[options]
module.file_ext=.vue
module.file_ext=.js
运行
npm run flow
为什么使用Flow?
- JavaScript是动态类型语言,他的灵活性有目共睹,但是过于灵活的副作用是很容易写出非常隐蔽的bug,在编译期甚至看上去都不会报错,但是在运行阶段就可能出现各种奇怪的bug
- 类型检查是当前动态类型语言的发展趋势,所谓类型检查,就是在编译期尽早发现(由类型错误引起的)bug,又不影响代码运行(不需要运行时态检查类型),使编写JavaScript具有和编写JAVA等强类型语言相近的体验
Flow的工作方式
-
通常类型检查分成2种方式
-
类型推断:通过变量的使用上下文来推断出变量类型,然后根据这些推断来检查类型。
-
类型注释:事先注释好我们期待的类型,Flow会基于这些注释来判断。
-
类型推断
function split(str) {
return str.split('')
}
split(11)
Flow 检查上述代码后会报错,因为函数 split 期待的参数是字符串,而我们输入了数字
类型注释
number类型
/*@flow*/
function add(x: number, y: number): number {
return x + y
}
add('Hello', 11)
现在 Flow 就能检查出错误,因为函数参数的期待类型为数字,而我们提供了字符串
数组类型
/*@flow*/
var arr: Array<number> = [1, 2, 3]
arr.push('Hello')
期望数组中每一项都是数字类型,如果这个数组添加了一个字符串,Flow 能检查出错误
类和对象
/*@flow*/
class Bar {
x: string; // x 是字符串
y: string | number | void; // y 可以是字符串或者数字或者不传
z: boolean;
constructor(x: string, y: string | number | void) {
this.x = x
this.y = y
this.z = false
}
}
// var bar: Bar = new Bar('hello') // 这里y是void不传 也可
var bar: Bar = new Bar('hello', 4)
var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
a: 'hello',
b: 11,
c: ['hello', 'world'],
d: new Bar('hello', 3)
}
对象的注释类型类似于类,需要指定对象属性的类型,new这个对象的时候第一个参数必须是字符串类型,第二个参数可以是字符串类型,可以是数字类型,也可以不传
Null
/*@flow*/
var foo: ?string = null
如果期望某个变量的类型是null或者undefined,写成 ?T 的格式即可
可选的函数参数
函数可以具有可选参数,其中问号 ? 出现在参数名称后面。同样,该参数不能为 null
function acceptsOptionalString(value?: string) {
// ...
}
acceptsOptionalString("bar"); // Works!
acceptsOptionalString(undefined); // Works!
acceptsOptionalString(null); // Error!
acceptsOptionalString(); // Works!
可选的对象属性
对象类型可以具有可选属性,问号 ? 位于属性名称后面。
propertyName?: string }
任意类型 any
使用any是完全不安全的,应尽可能避免
function add(one: any, two: any): number {
return one + two;
}
add(1, 2); // Works.
add("1", "2"); // Works.
add({}, []); // Works.