🚙 TypeScript 函数类型
# 函数的类型
在 JavaScript 中,函数是重要的组成部分,并且函数可以作为一等公民(可以作为参数,也可以作为返回值进行传递)
- 在使用函数的过程中,函数也可以有自己的类型,可以编写函数函数类型的表达式(Function Type Expressions),来表示函数类型;
type CalcFunc = (num1: number, num2: number) => void
function calc(fn: CalcFunc) {
console.log(fn(20, 30))
}
function sum(num1: number, num2: number) {
return num1 + num2
}
function mul(num1: number, num2: number) {
return num1 * num2
}
calc(sum)
calc(mul)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 上面
(num1: number, num2: number) => void
代表的就是一个函数类型。
- 接收两个参数的函数:
num1
和num2
,并且都是number
类型。- 并且这个函数没有返回值,所有是
void
。- 某些语言中,
num1
和num2
可以省略,但是 TypeScript 不可以省略。
# 参数的可选类型
函数的某个参数是可选的:
function foo(x: number, y?: number) {
console.log(x,y)
}
1
2
3
2
3
这个时候参数 x
依然是有类型的,它的类型是 number | undefined
。
另外可选类型需要在必传参数的后面否则报错,如下错误示范:
function foo(x?: number, y: number) {
// A required parameter cannot follw an optional parameter.
console.log(x,y)
}
1
2
3
4
2
3
4
# 默认参数
从 ES6 开始,JavaScript 是支持默认参数的,TypeScript 也是支持默认参数的。
例子:
function foo(x: number, y: number = 6) {
console.log(x, y)
}
foo(10)
1
2
3
4
5
2
3
4
5
此时的
y
是undefined
和number
的联合类型。
# 剩余参数
从 ES6 开始,JavaScript 也支持剩余参数,剩余参数语法允许将一个不定数量的参数放到一个数组中。
function sum(...nums: number[]) {
let total = 0
for (const num of nums){
total += num
}
return total
}
const result1 = sum(10, 20, 30)
console.log(result1)
const result2 = sum(10, 20, 30, 40)
console.log(result2)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# this
# 可推导的 this
类型
先观察一个例子:
const info = {
name: 'simon',
sayHello() {
console.log(this.name)
}
}
info.sayhello()
1
2
3
4
5
6
7
2
3
4
5
6
7
这个例子可以正常运行。也就是说 TypeScript 在编译时,认为 this
是可以正确去使用的。TypeScript 认为函数 sayHello
有一个对应的 this
的外部对象 info
,所以在使用时,就会把 this
当做该对象。
# 不确定的 this
类型
但在某些情况下,并不清楚 this
的指向:
function sayHello(){
console.log(this.name)
}
const info = {
name: 'simon',
sayHello
}
info.sayHello() // error 编译器报错
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- TypeScript 进行类型检测的目的是让代码更加的安全;
- 所以这里对于
sayHello
的调用来说,虽然将其放到了info
中,通过info
去调用,this
依然是指向info
对象的; - 但是对于 TypeScript 编译器来说,这个代码是非常不安全的,因为也有可能直接调用函数,或者通过别的对象来调用函数。所以 TypeScript 不允许
this
的不确定情况发生,所以要指定this
的类型。
# 指定的 this
类型
当 this
的类型不确定时,TypeScript 需要指定 this
的类型:
type NameType = {
name: string
}
function sayHello(this: nameType){
console.log(this.name)
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 函数的重载
🌰 例子:当写了一个 add
函数,希望可以对字符串和数字进行相加:
function sum(a1: number | string, a2: number | string): number | string {
return a1 + a2 // 报错,不能实现联合类型的相加
}
1
2
3
2
3
** 可以编写不同的重载签名(overload signatures)来表示函数可以以不同的方式进行调用。** 一般是编写两个或者以上的重载签名,再去编写一个通用的函数以及实现。
对于 sum
函数的重载:
- 在调用
sum
函数时,会根据传入的参数类型决定执行函数体时,到底执行哪一个函数的重载签名:
function sum(a1: number, a2: number): number;
function sum(a1: string, a2: string): string;
function sum(a1: any, a2: any): any {
return a1 + a2
}
console.log(sum(1,1))
console.log(sum('aaa', 'bbb'))
// 注意下面:有的实现体函数不能直接被调用
sum({name: 'simon'}, {age: 18})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 联合类型的重载
🌰 例子:需求,定义一个函数,可以传入字符串或者数组,获取它们的长度。有两种实现方案:
使用联合类型:
function getLength(a: stirng|any[]){ return a.length }
1
2
3实现函数的重载:
function getLength(a: string): number; function getLength(a: any[]): number; function getLength(a: any) { return a.length }
1
2
3
4
5
在实际开发中,尽量使用联合类型实现。
编辑 (opens new window)
📢 上次更新: 2022/09/02, 10:18:16