JavaScript 是一门弱类型且动态类型的语言,数据类型没有约束,有时候会引发一些问题。可以借助 Flow 这样一款静态类型检测工具来弥补 JavaScript 类型系统的缺陷。
上手
Flow 是一个 npm 模块。安装后需要初始化配置。
npm i flow-bin -Dnpx flow --init
在 js 文件开头写上 @flow 的注释, Flow 就能识别到这个文件需要检测。
// @flowfunction sum (a: number, b: number) {return a + b}sum(100, 100)sum('100', '100') // 报错
如果检测没有问题,那么需要移除掉类型注解,因为原生 JavaScript 并不支持。可以用官方的 flow-remove-types 模块或者用 Babel + @babel/preset-flow。
npm i flow-remove-types @babel/cli @babel/core @babel/preset-flow -D
如果使用 Babel,需要添加配置文件 .babelrc:
{"presets": ["@babel/preset-flow"]}
使用方法:
npx flow-remove-types 目标文件夹 -d 输出文件夹npx babel 目标文件夹 -d 输出文件夹
使用 Flow 官方提供的 vs code 插件,可以更直观地在编译器看到类型错误的提示,不用每次都输入命令。
类型推断
Flow 会根据代码自动推断参数应该是什么数据类型。
/*** 类型推断** @flow*/function square (n) {return n * n}// square('100') 因为 square 里面对传入的参数使用了乘法,所以 Flow 会自动推断传入参数应该是数字square(100)
类型注解
/*** 类型注解** @flow*/function square (n: number) {return n * n}let num: number = 100// num = 'string' // errorfunction foo (): number {return 100 // ok// return 'string' // error}function bar (): void {// return undefined}
数据类型
原始数据类型
/*** 原始类型** @flow*/const a: string = 'foobar'const b: number = Infinity // NaN // 100const c: boolean = false // trueconst d: null = nullconst e: void = undefinedconst f: symbol = Symbol()
数组
/*** 数组类型** @flow*/const arr1: Array<number> = [1, 2, 3]const arr2: number[] = [1, 2, 3]// 元组const foo: [string, number] = ['foo', 100]
对象
/*** 对象类型** @flow*/const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 }const obj2: { foo?: string, bar: number } = { bar: 100 }const obj3: { [string]: string } = {}obj3.key1 = 'value1'obj3.key2 = 'value2'
函数
/*** 函数类型** @flow*/function foo (callback: (string: string, number: number) => void) {callback('string', 100)}foo(function (str, n) {// str => string// n => number})
特殊类型
/*** 特殊类型** @flow*/// 字面量类型const a: 'foo' = 'foo' // 只能是 fooconst type: 'success' | 'warning' | 'danger' = 'success' // 只能是其中一个// ------------------------// 声明类型type StringOrNumber = string | numberconst b: StringOrNumber = 'string' // 100// ------------------------// Maybe 类型const gender: ?number = undefined// 相当于// const gender: number | null | void = undefined
Mixed 和 Any
Mixed 和 Any 表示任意类型,区别在于 Mixed 是强类型的,Any 是弱类型的。如果调用一些专属的类型方法,Mixed 需要先明确是这种类型。
/*** Mixed Any** @flow*/// string | number | boolean | ....function passMixed (value: mixed) {if (typeof value === 'string') {value.substr(1)}if (typeof value === 'number') {value * value}}passMixed('string')passMixed(100)// ---------------------------------function passAny (value: any) {value.substr(1)value * value}passAny('string')passAny(100)
