Vue.js源码利用了Flow做了静态类型检查

为什么用Flow

  • javascript动态语言类型,比较灵活,但是灵活的副作用是容易写出隐蔽的隐藏代码
  • 在编译期看上去不会报错,但是在运行阶段就可能出现各种奇怪的bug
  • 所谓类型检查,就是在编译期尽早发现(由类型错误引起的)bug,又不影响代码运行(不需要运行时动态检查类型),使编写 JavaScript 具有和编写 Java 等强类型语言相近的体验
  • 项目越复杂就越需要通过工具的手段来保证项目的维护性和增强代码的可读性
  • Vue.js在2.0重构时在ES2015基础上除了ESLint保证代码风格外,也引入了Flow做静态类型检查
  • 选择Flow主要是因为Babel 和 ESLint 都有对应的 Flow 插件以支持语法,可以完全沿用现有的构建配置,非常小成本的改动就可以拥有静态类型检查的能力

    工作方式

    类型推断

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

    类型注释

    事先注释好我们期待的类型,Flow会根据这些注释来判断

    类型推断

    ```javascript /@flow/

function split(str) { return str.split(‘ ‘) }

split(11)

  1. Flow检查时会报错,因函数split期待参数是字符串而却传入的是数字
  2. <a name="RyagJ"></a>
  3. ## 类型注释
  4. ```javascript
  5. /*@flow*/
  6. function add(x, y){
  7. return x + y
  8. }
  9. add('Hello', 11)

Flow检查不出任何错误,因+既可以用在字符串上也可以用在数字上
在这种情况下借助类型注释来指明期望的类型:

  • 类型注释以冒号 : 开头
  • 可以在函数参数、返回值、变量声明中使用 ```javascript /@flow/

function add(x: number, y: number): number { return x + y }

add(‘Hello’, 11)

  1. Flow检查出错误,期待类型为数字却传入的是字符串
  2. <a name="D2f45"></a>
  3. ## 数组
  4. ```javascript
  5. /*@flow*/
  6. var arr: Array<number> = [1, 2, 3]
  7. arr.push('Hello')

数组类型注释的格式是 Array,T 表示数组中每项的数据类型
给这个数组添加一个字符串Flow能检查出错误

类和对象

  1. /*@flow*/
  2. class Bar {
  3. x: string; // x 是字符串
  4. y: string | number; // y 可以是字符串或者数字
  5. z: boolean;
  6. constructor(x: string, y: string | number) {
  7. this.x = x
  8. this.y = y
  9. this.z = false
  10. }
  11. }
  12. var bar: Bar = new Bar('hello', 4)
  13. var obj: { a: string, b: number, c: Array<string>, d: Bar } = {
  14. a: 'hello',
  15. b: 11,
  16. c: ['hello', 'world'],
  17. d: new Bar('hello', 3)
  18. }

类的类型注释可以对类自身的属性做类型检查,也可以对构造函数的参数做类型检查

Null

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

  1. /*@flow*/
  2. var foo: ?string = null

foo可以为字符串可以为null