函数是 JavaScript 中的一等公民(参考1,参考2)。ECMAScript 中定义函数的方式有两种:函数声明 ( Function Declaration ) 与函数表达式 ( Function Expression ) 。
1 函数声明
TypeScript 中对于函数声明形式定义的函数类型约束较为简单
function sum(num1: number, num2: number): number {return num1 + num2;}
调用函数时,传入的参数类型与参数个数和返回的值类型都是确定的。
/*** 产生三处错误*/// ERROR: 1 不能将类型“number”分配给类型“string”。// ERROR: 2 类型“string”的参数不能赋给类型“number”的参数。// ERROR: 3 应有 2 个参数,但获得 3 个。let result: string = sum(1,'2',3);
2 函数表达式
TypeScript 中对于函数表达式的类型约束则较为复杂,不仅要约束表达式式右边的匿名函数,还要约束表达式左边的变量类型。如
let mySum: (num1: number, num2: number) => number = function (num1: number, num2: number): number {return num1 + num2;}
❗注:上述表达式左边的 => 不是 ES6 中的箭头函数,而是 TypeScript 中的函数类型定义。
3 函数的接口
上述函数表达式过于复杂,可以通过接口 (Interfaces) 来代替。
interface ISum {(num1: number, num2: number): number}let mySum2: ISum;mySum2 = function(num1: number, num2: number): number {return num1 + num2;}
4 可选参数
前面提到, TypeScript 在定义函数约束时,也约束了参数的个数,如果某些情况我们需要参数不定个数,就需要用到与对象的可选属性类似的可选参数。
function buildName(firstName: string, lastName?: string): string {if (lastName) {return firstName + " " + lastName;} else {return firstName;}}let tomcat = buildName("Tom", "Cat");let tom = buildName("Tom");
5 参数默认值
ES6 中允许给函数参数设置默认值,在未传入该参数,或传入参数值为 undefined 时默认值生效; TypeScript 中也允许对函数参数进行类型约束时使用默认值,它会将带有默认值的参数识别为可选参数,且不再要求后面不能再出现确定参数的约束了。
function buildName(firstName: string = "Tom", lastName: string): string {return firstName + " " + lastName;}let tomcat = buildName("Tom", "Cat");let cat = buildName(undefined, "Cat");
6 剩余参数
ES6 中允许函数使用 ...rest 语法,将未显式接受的剩余参数聚合到一个数组中,因此 TypeScript 能够使用数组类型对其剩余参数进行类型约束。
function push(array: any[], ...items: any[]): void {items.forEach(function (item) {array.push(item);});}let a = [];push(a, 1, 2, 3);
7 函数重载
有时候需要对函数接收到不同类型的参数做不同类型的处理,这需要用到重载。如编写一个反转函数 reverse ,实现输入数字将其反转后输出数字,输入字符串也将其反转后输出文本。
function reverse(input: number | string): number | string {if(typeof input === "number") {return Number(input.toString().split('').reverse().join(''));}return input.split('').reverse().join('');}
上述函数虽然能够编译通过,且实现相应的功能,但不能准确表达它的参数及其返回结果类型。因此为了友好提示,可以使用 TypeScript 的函数重载,准确表示各种类型下的处理情况:
function reverse(input: number): number; // 重载1function reverse(input: string): string; // 重载2// 具体实现function reverse(input: number | string): number | string {if(typeof input === "number") {return Number(input.toString().split('').reverse().join(''));}return input.split('').reverse().join('');}
这样一来,就能准确的表示各种类型下的处理情况,编辑器也会产生友好提示。
