参考
https://ts.xcatliu.com/basics/type-of-function.html
https://jkchao.github.io/typescript-book-chinese/typings/functions.html
函数是JavaScript中传递数据的主要手段。TypeScript允许你指定函数的输入和输出值的类型。
函数(已实现)注解(参数和返回)
参数类型注解
当你声明一个函数时,你可以在每个参数后面添加类型注解,以声明该函数接受哪些类型的参数。参数类型注解位于参数名称之后。
// Parameter type annotation
function greet(name: string) {
console.log("Hello, " + name.toUpperCase() + "!!");
}
当一个参数有类型注解时,该函数的参数将被检查。
即使你的参数上没有类型注解,TypeScript 仍然会检查你是否传递了正确数量的参数。
返回类型注解
你也可以添加返回类型注解。返回类型注解出现在参数列表的后面。
function getFavoriteNumber(): number {
return 26;
}
与变量类型注解一样,你通常不需要返回类型注解,因为TypeScript将根据其返回语句推断出函数的返回类型。上面的例子中的类型注解并没有改变任何东西。一些代码库会明确指定一个返回类型,以达到文档的目的,防止意外的改变,或者只是出于个人的偏好。
匿名函数
匿名函数与函数声明有一点不同。当一个函数出现在TypeScript可以确定它如何被调用的地方时,该函数的参数会自动给出类型。
这里有一个例子。
// No type annotations here, but TypeScript can spot the bug
const names = ["Alice", "Bob", "Eve"];
// Contextual typing for function
names.forEach(function (s) {
console.log(s.toUppercase());
Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
// Contextual typing also applies to arrow functions
names.forEach((s) => {
console.log(s.toUppercase());
Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});
尽管参数s没有类型注释,但TypeScript使用forEach函数的类型,以及数组的推断类型,来确定s的类型。
这个过程被称为上下文类型化,因为函数发生的上下文告知了它应该有什么类型。
与推理规则类似,你不需要明确地学习这种情况是如何发生的,但是理解它确实发生了,可以帮助你注意到什么时候不需要类型注释。稍后,我们将看到更多关于一个值发生的上下文如何影响其类型的例子。
函数表达式
如果要我们现在写一个对函数表达式(Function Expression)的定义,可能会写成这样:
let mySum = function (x: number, y: number): number { return x + y; };
这是可以通过编译的,不过事实上,上面的代码只对等号右侧的匿名函数进行了类型定义,而等号左边的 mySum,是通过赋值操作进行类型推论而推断出来的。如果需要我们手动给 mySum 添加类型,则应该是这样:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number { return x + y; };
注意不要混淆了 TypeScript 中的 => 和 ES6 中的 => (参考下面函数声明)
函数(未实现)声明
对象形式描述函数形状(type和interface都可以)
type LongHand = {
(a: number): number;
};
也可以用接口定义函数的形状,与type作用一样
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
函数表达式形式定义函数类型
type ShortHand = (a: number) => number;
在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
注意不要混淆了 TypeScript 中的 => 和 ES6 中的 =>
使用区别
上面代码中的两个例子完全相同。但是,当你想使用函数重载时,只能用第一种方式
type LongHandAllowsOverloadDeclarations = {
(a: number): number;
(a: string): string;
};