在JavaScript中,函数可以作为一个整体赋值给一个变量:
// javascript代码
let fn = function(){}
既然函数可以作为值赋给变量,那么函数就应该有自己的类型。上述代码用TypeScript等价表示如下:
// ()=>void 是变量fn的类型,代表是一个函数类型
let fn: () => void;
fn = function(){}
上例中,() => void
就是变量 fn
的类型注解,也就是函数类型。
// 这里的箭头=>用于类型声明
(p1: T1, p2: T2, ...) => T
在TypeScript中,函数定义相对于JavaScript的区别就是可以显式的为参数和返回值添加类型注解:
// javascript函数定义
function sum(a, b) {
return a + b;
}
// 改为typescript函数定义
function sum(a: number, b: number): number {
return a + b;
}
直接定义的函数有自己的隐式函数类型,比如对于上述函数定义
function sum(a: number, b: number): number {
return a + b;
}
编译器会推导出 sum
函数具有类型:
(a: number, b: number) => number;
通过类型查询,可以获取一个直接定义的函数的类型:
// 直接定义的函数
function sum(a: number, b: number): number {
return a + b;
}
// 通过typeof关键字获取函数sum的类型为:
// (a: number, b: number) => number;
let fn: typeof sum;
// 将类型兼容的函数赋值给fn
fn = function(x: number, y: number): number {
return x + y;
}
判断一个函数类型是否和一个函数兼容,只需判断参数类型和返回值类型是否同时兼容:
// 声明fn为函数类型
let fn: (x: number, y: string) => boolean;
// 正确,参数名字不做兼容检查
fn = function(a: number, b: string): boolean {
// ...
return true;
}
// 正确,允许值的参数比声明参数少
fn = function(a: number): boolean {
// ...
return true;
}
// 错误,函数返回值类型不匹配
// error TS2322: Type '(a: number, b: string) => string' is not assignable to type '(x: number, y: string) => boolean'
fn = function(a: number, b: string): string {
// ...
return b;
}
// 错误,参数过多
// error TS2322: Type '(a: number, b: string, c: number) => boolean' is not assignable to type '(x: number, y: string) => boolean
fn = function(a: number, b: string, c: number): boolean {
// ...
return true;
}
// 错误,参数类型不匹配,第二个参数应该为 string 类型
// error TS2322: Type '(a: number, b: boolean) => boolean' is not assignable to type '(x: number, y: string) => boolean'
fn = function(a: number, b: boolean): boolean {
// ...
return true;
}
// 错误,返回值类型不匹配,应该为 boolean
// error TS2322: Type '(a: number, b: string) => void' is not assignable to type '(x: number, y: string) => boolean'
fn = function(a: number, b: string): void {
// ...
}
可选参数在调用时可以不必传参;而必选参数在调用时必须传参。在参数的类型注解前添加 ?
即可让参数成为可选参数:
// 参数a必须,参数b可选,b必须位于a之后
function test(a: number, b?: number): void {
// ...
}
// 正确,忽略可选参数
test(1);
// 正确,传递可选参数
test(1, 2);
// 错误,必选参数a未传递
// error TS2554: Expected 1-2 arguments, but got 0
test();
必须注意的是可选参数必须位于必选参数之后,下面的定义就是不合法的:
// 错误,可选参数之后不能有必选参数
// error TS1016: A required parameter cannot follow an optional parameter
function test(a?: number, b: number): void {
// ...
}