feng xiaohan

函数的类型

函数声明(定义)

一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到,其中函数声明的类型定义较简单:

function sum(x: number, y: number): number {
  return x + y;
}

注意,输入多余的(或者少于要求的)参数,是不被允许的

function sum(x: number, y: number): number {
  return x + y;
}
sum(1, 2, 3);

// index.ts(4,1): error TS2346: Supplied parameters do not match any signature of call target.

函数表达式

let mySum = function (x: number, y: number): number {
  return x + y;
};
// 实际
let mySum: (x: number, y: number) => number = function (
  x: number,
  y: number
): number {
  return x + y;
};

在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。

箭头函数

let add = (a: number, b: number): number => a + b;

用接口定义函数的形状

我们也可以使用接口的方式来定义一个函数需要符合的形状:

interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function (source: string, subString: string) {
  return source.search(subString) !== -1;
};

采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

可选参数

与接口中的可选属性类似,我们用 ? 表示可选的参数:

function buildName(firstName: string, lastName?: string) {
  if (lastName) {
    return firstName + " " + lastName;
  } else {
    return firstName;
  }
}
let tomcat = buildName("Tom", "Cat");
let tom = buildName("Tom");

注意:可选参数后面不允许再出现必须参数。

参数默认值

在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数

function buildName(firstName: string, lastName: string = "Cat") {
  return firstName + " " + lastName;
}
let tomcat = buildName("Tom", "Cat");
let tom = buildName("Tom");

此时就不受「可选参数必须接在必需参数后面」的限制了:

function buildName(firstName: string = "Tom", lastName: string) {
  return firstName + " " + lastName;
}
let tomcat = buildName("Tom", "Cat");
let cat = buildName(undefined, "Cat");

注意:可选参数和默认参数不能同时使用。

剩余参数(*)

ES6 中,可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数):

function push(array, ...items) {
  items.forEach(function (item) {
    array.push(item);
  });
}

let a: any[] = [];
push(a, 1, 2, 3);

事实上,items 是一个数组。所以我们可以用数组的类型来定义它:

function push(array: any[], ...items: any[]) {
  items.forEach(function (item) {
    array.push(item);
  });
}

let a = [];
push(a, 1, 2, 3);

this

ts 允许定义 this 的类型(js 不能),函数的第一个参数可以定义 this 的类型。

interface Obj {
  user: number[];
  add: (this: Obj, num: number) => void; // 定义this的类型为Obj,传递的参数类型为number,函数没有返回值
}
let obj: Obj = {
  user: [1, 2, 3],
  add(this: Obj, num: number) {
    this.user.push(num);
  },
};

obj.add(4);

函数重载

允许一个函数接受不同数量或类型的参数时,作出不同的处理

let users: number[] = [1, 23, 4];
function findNum(): number[]; // 如果什么都不传入则查询全部
function findNum(id: number): number[]; // 传入id则根据id查询
function findNum(add: number[]): number[]; // 传入number类型数组就将其添加到数组里
function findNum(id?: number | number[]): number[] {
  if (typeof id == "number") {
    return users.filter((uId) => uId == id);
  } else if (Array.isArray(id)) {
    user.push(...id);
  } else {
    return user;
  }
}

console.log(findNum()); // [1,23,4]
console.log(findNum(4)); // [4]
console.log(findNum([6, 7, 9])); // [1,23,4,6,7,9]