Flow 的价值、工作方式,以及和 TypeScript 的取舍
2023-03-02 11:12:31
Flow 和 TypeScript 解决的是同一类问题:给 JavaScript 增加静态类型检查,让一部分错误在开发阶段暴露出来,而不是等到运行时才发现。
为什么需要静态类型
JavaScript 是动态类型语言,灵活是它的优势,也是大型项目里的风险来源。
function formatPrice(price) {
return price.toFixed(2)
}
formatPrice('12.3')
这段代码在编写时不会报错,但运行时会因为字符串没有 toFixed 方法而失败。静态类型检查的价值就在于:在代码真正运行之前,提前发现这类由类型不匹配导致的问题。
在项目规模变大后,类型系统还能带来几个工程收益:
- 减少隐蔽 bug:函数参数、返回值、对象字段不匹配时可以提前发现
- 提升可读性:类型本身就是一种文档,能说明数据结构和函数契约
- 增强重构信心:修改接口、字段名、返回值时,类型检查可以指出受影响的位置
- 改善编辑器体验:补全、跳转、重命名、引用查找都更可靠
Flow 的工作方式
Flow 主要通过两种方式理解代码类型:类型推断和类型注解。
类型推断
Flow 会根据变量的初始值和使用方式推断类型。
// @flow
let count = 1
count = '1'
count 初始值是数字,后续再赋值为字符串时,Flow 就可以发现类型不一致。
类型注解
对于函数参数、返回值、复杂对象,显式类型注解更清晰。
// @flow
function sum(a: number, b: number): number {
return a + b
}
sum(1, '2')
类型注解的作用不是改变运行时代码,而是在开发阶段提供检查。最终代码仍然需要经过 Babel 等工具移除类型语法后再运行。
Vue 2 为什么选择 Flow
Vue 2 在重构时选择 Flow,主要原因是当时 Flow 更适合直接叠加到已有 JavaScript 工程中:
- 可以保持 JavaScript 文件为主,不需要全面切换到
.ts - Babel 和 ESLint 都有 Flow 相关插件,接入成本较低
- Flow 的类型推断能力适合渐进式迁移,不需要一次性补齐全部类型
- 对于框架源码来说,静态类型可以约束内部复杂的数据结构和函数调用关系
所以,Vue 2 使用 Flow 的核心原因不是“Flow 比 TypeScript 永远更好”,而是在当时的生态、迁移成本和工具链条件下,Flow 是一个更轻量的选择。