类型注解

JavaScript 是一门动态类型语言,语法上也没规定要明确表示类型。 下面是正常的 JavaScript 代码

1
2
3
4
5
function add(num1, num2) {
  return num1 + num2;
}
var x = add(3, '0');
console.log(x);

x 的值是什么? 3 还是 "30"?还是 undefined 呢? 答案是 "30"。 很多时候,这可能不是你想要的。

Flow 通过静态分析和类型注解,让你减少这类隐晦的 bug,让代码更加符合预期。

类型注解#

类型注解通常都以 : 开头,可以用在方法参数和返回值,还有变量声明,例如:

1
2
3
4
5
6
function foo(a: string, b: number): void { ... }
var x: boolean = someBool;
class Bar {
  y: string;
  someMethod(a: number): string { ... }
}

简单例子#

可以简单地添加 @flow 作为注释,让 Flow 检测它

1
2
3
4
5
6
/* @flow */
function add(num1, num2) {
  return num1 + num2;
}
var x = add(3, '0');
console.log(x);

不过,Flow 没能发现任何错误。这是因为 + 运算符能够支持 numberstring 类型的值,我们也没有明确指名参数类型必须为 number

1
2
3
4
5
6
/* @flow */
function add(num1: number, num2: number): number {
  return num1 + num2;
}
var x: number = add(3, '0');
console.log(x);

对上面代码执行类型检测,于是给出类型错误了,因为我们明确声明了参数和变量的类型

file.js:5
  5: var x: number = add(3, '0');
                     ^^^^^^^^^^^ function call
  5: var x: number = add(3, '0');
                            ^^^ string. This type is incompatible with
  2: function add(num1: number, num2: number): number {
                                      ^^^^^^ number

Found 1 error

类型注解是必须的吗#

用上 Flow 并不意味一定要类型注解,唯一必须的就是上面提到的 @flow 注解. 就像上面的例子,这行注释让 Flow 知道要检测代码

1
2
3
4
5
6
/* @flow */
function multPI(num1, num2) {
  return Math.PI * num1 * num2;
}
var x = multPI(3, '0');
console.log(x);

因为 * 操作符不支持字符串运算,Flow 很聪明,无需类型注解就能够推断出问题

file.js:5
  5: var x = multPI(3, '0');
             ^^^^^^^^^^^^^^ function call
  3:   return Math.PI * num1 * num2;
                               ^^^^ string. This type is incompatible with
  3:   return Math.PI * num1 * num2;
              ^^^^^^^^^^^^^^^^^^^^^ number

Found 1 error

模块界限#

在跨模块使用的时候,Flow 需要明确注解。 为了保证 Flow 在各自模块内的独立检测,不去探测别的模块的调用,提高性能。 刚好这也提升了模块化编程中代码即文档的风格。

1
2
3
4
5
6
7
8
9
/**
 * Size.js
 * @flow
 */
function size(input: string): number {
  return input.length;
}

module.exports = size;
1
2
3
4
5
6
/**
 * UseSize.js
 * @flow
 */
var size = require('./Size');
var result = size(null);

Size.jssize 方法必须要类型注解,因为 UseSize.js 用到它, 因为不能夸模块探测,别的模块怎么使用我的方法我不知道, 所以我必须明确声明类型,暴露出去的时候,别人就知道我的要求了。

UseSize.js:6
  6: var result = size(null);
                  ^^^^^^^^^^ function call
  6: var result = size(null);
                       ^^^^ null. This type is incompatible with
  5: function size(input: string): number {
                          ^^^^^^ string. See: Size.js:5

Found 1 error

any 注解#

any 是一个特殊的类型注解,代表任何动态类型。 any 能够表示任何类型,当然也能接受任何类型。 any 就意味着 “别检查我,我知道我在干嘛”。

两个字#

你可以处处写上注解,这能充分表达你的代码意图。 不过 Flow 也有很多类型接口来减轻你的负担。 唯一必须要类型注解的就是模块间调用的资源。

← Prev Next →

You can edit this page on GitHub and send us a pull request!