携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情
😊 大家好,我是思淼MJ。
上篇文章总结了 TypeScript 的数组类型,今天继续来总结 TypeScript 的另一种类型。
函数类型
说到“函数类型”,就会想到JavaScript 中的“函数表达式”,那来结合JavaScript 中的函数表达式来对函数类型总结一下。
函数声明
在 JavaScript 中,有两种比较常见的定义函数的方式:函数声明和函数表达式。
先来举个简单的例子🌰:
// 函数声明
fonction getSum (x, y) {
return x + y;
}
// 函数表达式
let getSum = fonction (x, y) {
return x + y;
}
上面的例子如果使用 TypeScript ,需要对输入和输出进行约束,函数声明的类型定义为:
fonction getSum (x:number, y:number):number {
return x + y;
}
🤔问题:在这种方式下,如果传递的参数多于或少于定义的参数,是被允许的吗?
📖答案:不允许。
比如上面的例子,我们调整为🌰:
fonction getSum (x:number, y:number):number {
return x + y;
}
getSum(1,2,3);
执行上面的代码,会发现有以下报错:
// error TS2346: Supplied parameters do not match any signature of call target.
当传递参数少于函数中定义的参数的时候,也会出现类似的报错信息。
所以,输入多于或少于函数中所要求的参数,是不被允许的。
函数表达式
如果首次将上面的函数表达式用 TypeScript 表达,可能会写成这样:
// 不知道有没有同学和我一样,写成这样😂
let getSum = fonction (x:number, y:number):number {
return x + y;
}
上面的例子,其实只是对等号的右侧的匿名函数进行了约束,而左侧的 getSum 的类型只是通过类型推断推导出它的类型,真实的代码应该是这样的:
let getSum:(x:number, y:number) => number = fonction (x:number, y:number):number {
return x + y;
}
🤔问题:那个 => 不是 ES6中的 箭头函数吗?
这里的 => 代表的含义并不同于 ES6 中的 箭头函数:
在 ES6 中,通常箭头的左侧代码是指 传递的参数,右侧是指,需要执行的功能逻辑;
而在 TypeScript 中,箭头的左侧代表输入的参数以及参数的类型,右侧则是指,输出结果的类型。
使用接口定义函数的形状
也可以通过使用接口来定义一个函数的形状,比如上面的例子🌰可以调整为:
interface sumType {
(x:number, y:number): number;
}
let getSum:sumType = function (x:number, y:number) {
return x + y;
}
通过上面的例子可以得出,使用接口定义函数的形状,简单来说就是对等号的左侧进行类型的限制约束。
可选参数
之前的文章中有提到过接口的“可选属性”,想必现在对“可选”的含义并不陌生。
前面有说到,输入多于或少于函数中要求的参数是不被允许的,那怎么才能定义参数为“可选参数”呢???
其实和接口的可选属性类似,使用 ? 表示可选的参数。
举个简单的例子🌰:
function getString (x:string, y?:string) {
if (y) {
return x + '+' + y;
} else {
return x
}
}
getString('a'); // 'a'
getString('a', 'b'); // 'a+b'
比如如果对上面的例子进行调整为:
function getString (x?:string, y:string) {
if (x) {
return x + '+' + y;
} else {
return y
}
}
getString(undefined, 'b');
执行了之后,会发现出现了以下报错:
// error TS1016: A required parameter cannot follow an optional parameter.
所以,需要注意的点是:可选参数必须写在必选参数的后面,也就是说可选参数的后面,不允许再出现必选参数。
参数默认值
在 ES6 中,可以给函数的参数添加默认值,在 TypeScript 中也是允许添加默认值的,会将添加的默认值的参数识别为可选参数。
举个简单的例子🌰:
function getString (x:string, y:string = '参数默认值') {
return x + y;
}
getString('a'); // 'a参数默认值'
getString('a', 'b'); // 'ab'
不同的点是:可选参数必须在必选参数的后面,而参数默认值不受这些的约束,可以放在任意位置。
剩余参数
在 ES6 中,可以使用 ... 的方式来获取函数中的剩余参数。
比如下面的例子🌰:
fonction getArr (array, ...items) {
items.map(item => {
array.push(item);
})
}
let a:any[] = [];
getArr(a, 1, 2, 3);
从上面的例子中,可以看出,items 是一个数组,所以可以使用数组类型来定义它,上面的例子即为:
fonction getArr (array:any[], ...items:any[]) {
items.map(item => {
array.push(item);
})
}
let a = [];
getArr(a, 1, 2, 3);
同时从上面的例子可以得出,剩余参数为最后一个参数。
重载
重载就是允许一个函数不同数量或者类型参数时,作出不同的方式处理。
举个简单的例子🌰,实现一个反转参数的方法,比如我们输入 123 ,输出 321;输入 ‘hello’,输出 ‘olleh’。
fonction reverse (x:string | number):string | number {
if (type of x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (type of x === 'string') {
return x.toString().split('').reverse().join('');
}
}
上面例子中的函数,有一个小小的缺点就是:
表达的不够精确,按理说应该输入的是字符串,输入的也应该是字符串;如果输入是数字,那输出就应该是数字。
这个时候,我们就可以使用 重载 来定义多个函数的类型。即:
fonction reverse(x:string):string;
fonction reverse(x:number):number;
fonction reverse (x:string | number):string | number {
if (type of x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (type of x === 'string') {
return x.toString().split('').reverse().join('');
}
}
上面例子中的含义是:前两次都是对函数的定义,最后一次是对函数的实现。
同时在编辑器中,我们可以明确的看到对变量中类型的提示。
需要注意的点是:TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。