函数是 JavaScript 中的一等公民(参考1参考2)。ECMAScript 中定义函数的方式有两种:函数声明 ( Function Declaration ) 与函数表达式 ( Function Expression ) 。

1 函数声明

TypeScript 中对于函数声明形式定义的函数类型约束较为简单

  1. function sum(num1: number, num2: number): number {
  2. return num1 + num2;
  3. }

调用函数时,传入的参数类型参数个数返回的值类型都是确定的。

  1. /**
  2. * 产生三处错误
  3. */
  4. // ERROR: 1 不能将类型“number”分配给类型“string”。
  5. // ERROR: 2 类型“string”的参数不能赋给类型“number”的参数。
  6. // ERROR: 3 应有 2 个参数,但获得 3 个。
  7. let result: string = sum(1,'2',3);

2 函数表达式

TypeScript 中对于函数表达式的类型约束则较为复杂,不仅要约束表达式式右边的匿名函数,还要约束表达式左边的变量类型。如

  1. let mySum: (num1: number, num2: number) => number = function (num1: number, num2: number): number {
  2. return num1 + num2;
  3. }

❗注:上述表达式左边的 => 不是 ES6 中的箭头函数,而是 TypeScript 中的函数类型定义。

3 函数的接口

上述函数表达式过于复杂,可以通过接口 (Interfaces) 来代替。

  1. interface ISum {
  2. (num1: number, num2: number): number
  3. }
  4. let mySum2: ISum;
  5. mySum2 = function(num1: number, num2: number): number {
  6. return num1 + num2;
  7. }

4 可选参数

前面提到, TypeScript 在定义函数约束时,也约束了参数的个数,如果某些情况我们需要参数不定个数,就需要用到与对象的可选属性类似的可选参数。

  1. function buildName(firstName: string, lastName?: string): string {
  2. if (lastName) {
  3. return firstName + " " + lastName;
  4. } else {
  5. return firstName;
  6. }
  7. }
  8. let tomcat = buildName("Tom", "Cat");
  9. let tom = buildName("Tom");

❗注:可选参数后面不能再出现确定参数

5 参数默认值

ES6 中允许给函数参数设置默认值,在未传入该参数,或传入参数值为 undefined 时默认值生效; TypeScript 中也允许对函数参数进行类型约束时使用默认值,它会将带有默认值的参数识别为可选参数,且不再要求后面不能再出现确定参数的约束了

  1. function buildName(firstName: string = "Tom", lastName: string): string {
  2. return firstName + " " + lastName;
  3. }
  4. let tomcat = buildName("Tom", "Cat");
  5. let cat = buildName(undefined, "Cat");

6 剩余参数

ES6 中允许函数使用 ...rest 语法,将未显式接受的剩余参数聚合到一个数组中,因此 TypeScript 能够使用数组类型对其剩余参数进行类型约束。

  1. function push(array: any[], ...items: any[]): void {
  2. items.forEach(function (item) {
  3. array.push(item);
  4. });
  5. }
  6. let a = [];
  7. push(a, 1, 2, 3);

7 函数重载

有时候需要对函数接收到不同类型的参数做不同类型的处理,这需要用到重载。如编写一个反转函数 reverse ,实现输入数字将其反转后输出数字,输入字符串也将其反转后输出文本。

  1. function reverse(input: number | string): number | string {
  2. if(typeof input === "number") {
  3. return Number(input.toString().split('').reverse().join(''));
  4. }
  5. return input.split('').reverse().join('');
  6. }

上述函数虽然能够编译通过,且实现相应的功能,但不能准确表达它的参数及其返回结果类型。因此为了友好提示,可以使用 TypeScript 的函数重载,准确表示各种类型下的处理情况:

  1. function reverse(input: number): number; // 重载1
  2. function reverse(input: string): string; // 重载2
  3. // 具体实现
  4. function reverse(input: number | string): number | string {
  5. if(typeof input === "number") {
  6. return Number(input.toString().split('').reverse().join(''));
  7. }
  8. return input.split('').reverse().join('');
  9. }

这样一来,就能准确的表示各种类型下的处理情况,编辑器也会产生友好提示。