函数类型(Function Types)
函数有两个应用类型检查的地方:参数(输入)和返回值(输出)。
// @flow
function concat(a: string, b: string): string {
return a + b;
}
concat("foo", "bar"); // Works!
// $ExpectError
concat(true, false); // Error!
使用类型推导可以省略类型定义
// @flow
function concat(a, b) {
return a + b;
}
concat("foo", "bar"); // Works!
// $ExpectError
concat(true, false); // Error!
函数语法
函数申明
function method(str, bool, ...nums) {
// ...
}
function method(str: string, bool?: boolean, ...nums: Array<number>): void {
// ...
}
箭头函数
let method = (str, bool, ...nums) => {
// ...
};
let method = (str: string, bool?: boolean, ...nums: Array<number>): void => {
// ...
};
函数类型
在这里你可以看到写入函数的类型的语法
(str: string, bool?: boolean, ...nums: Array<number>) => void
你也可以选择省略参数名称。
(string, boolean | void, Array<number>) => void
你可能会在回调函数中使用这些函数类型。
function method(callback: (error: Error | null, value: string | null) => void) {
// ...
}
函数参数
函数参数添加类型的方式是在参数名称后面添加:
。
function method(param1: string, param2: boolean) {
// ...
}
可选函数参数
函数添加可选参数的方式是在参数的名字和冒号:
之前添加?
。
function method(optionalValue?: string) {
// ...
}
可选参数可以接收匹配类型,undefined
或被省略,但不能接收nul
// @flow
function method(optionalValue?: string) {
// ...
}
method(); // Works.
method(undefined); // Works.
method("string"); // Works.
// $ExpectError
method(null); // Error!
Rest参数
JavaScript支持在参数列表的末尾接收剩余参数或数组参数。他们面前有一个...
。
function method(...args: Array<number>) {
// ...
}
// @flow
function method(...args: Array<number>) {
// ...
}
method(); // Works.
method(1); // Works.
method(1, 2); // Works.
method(1, 2, 3); // Works.
注意
rest
参数必须是Array
类型
函数返回
函数返回也可以使用:类型
。
function method(): number {
// ...
}
返回类型确保函数的每个分支都返回相同的类型。这可以防止你在特定条件下意外不返回值。
// @flow
// $ExpectError
function method(): boolean {
if (Math.random() > 0.5) {
return true;
}
}
函数 this
JavaScript中的每个函数都可以被一个名为`this`的特殊上下文调用。你可以用你想要的任何上下文来调用一个函数。
在Flow中,你不需要键入注释,Flow将检查你调用该函数的任何上下文。
function method() {
return this;
}
var num: number = method.call(42);
// $ExpectError
var str: string = method.call(42);
谓词函数
谓词函数是一个判断式,一个返回bool值的函数或者仿函数:P:X→{true,false}
,称为X上的谓词。
有时你会想从if语句中移动条件到一个函数中,但是,Flow将在下面的代码中标记一个错误:
function truthy(a, b): boolean {
return a && b;
}
function concat(a: ?string, b: ?string): string {
if (truthy(a, b)) {
// $ExpectError
return a + b;
}
return '';
}
你可以通过使用%checks
注解来修复这个问题,方法如下:
function truthy(a, b): boolean %checks {
return !!a && !!b;
}
function concat(a: ?string, b: ?string): string {
if (truthy(a, b)) {
return a + b;
}
return '';
}
这些谓词函数的主体必须是表达式(即不支持局部变量声明)。但是可以在谓词函数中调用其他的谓词函数。例如:
function isString(y): %checks {
return typeof y === "string";
}
function isNumber(y): %checks {
return typeof y === "number";
}
function isNumberOrString(y): %checks {
return isString(y) || isNumber(y);
}
function foo(x): string | number {
if (isNumberOrString(x)) {
return x + x;
} else {
return x.length; // no error, because Flow infers that x can only be an array
}
}
foo('a');
foo(5);
foo([]);
函数类型
如果需要函数接收任意类型的函数,对于那些你应该写()=>
混合的类型:
function method(func: () => mixed) {
// ...
}
但是,如果你想要退出类型检查,并且不使用any
,那么可以使Function
类型。 Function
类型是不安全的,应该避免。
function method(func: Function) {
func(1, 2); // Works.
func("1", "2"); // Works.
func({}, []); // Works.
}
method(function(a: number, b: number) {
// ...
});
Function
类型等同于any
类型