Skip to content

Latest commit

 

History

History
161 lines (116 loc) · 3.71 KB

函数类型.md

File metadata and controls

161 lines (116 loc) · 3.71 KB

函数类型

在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 {
  // ...
}