函数的类型
函数声明
在 javascript 中有两种常见的定义函数方法—函数声明和函数表达式
//函数声明
function sum(x, y) {
return x + y
}
//函数表达式
let mysum = function (x, y) {
return x + y
}
一个函数有输入和输出,要在 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)
//直接错误
- 第二种错误
function sum(x: number, y: number) {
return x + y
}
sum(1)
函数表达式
- 如果我们现在要写一个函数表达式,可能会写成这样
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 中的=>和 ES6 中的=>
在 Typescript 的类型定义中, =>用来表示函数的定义,左边是输入类型,需要括号括起来。右边是输出类型
在 ES6 中, =>表示箭头函数
接口也可以定义函数
- 我们用接口的方式定义一个函数
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')
特别注意的就是 可选参数必须接在必修参数后面,换句话说,可选参数后面不允许再出现必修参数了
function buildName(firstName?: string, lastName: string) {
if (lastName) {
return firstName + '' + lastName
} else {
return firstName
}
}
let tomcat = buildName('Tom', 'Cat')
let tom = buildName(undefined, 'Tom')
// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.
参数默认值
在 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)
重载
重载允许一个函数接受不同数量或类型的参数时,作出不同的处理
比如,我们需要实现一个函数 reverse,输入数字 123 的时候,输出反转的数字 321,输入字符串 ‘hello’ 的时候,输出反转的字符串 ‘olleh’
利用联合类型,我们可以这样实现:
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''))
} else if (typeof x === 'string') {
return x.split('').reverse().join('')
}
}
然而这样有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。
- 我们可以使用重载定义多个 reverse 的函数类型
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}