
四、TypeScript-函数&this
一、函数类型
在 JavaScript 开发中,函数是重要的组成部分,并且函数可以作为一等公民(可以作为参数,也可以作为返回值进 行传递)
那么在使用函数的过程中,函数是否也可以有自己的类型呢?
我们可以编写函数类型的表达式(Function Type Expressions),来表示函数类型;
1 | function foo() {} |
() => void 表示函数类型
举例:
1 | type Func = (n1: number, n2: number) => void; |
应该能绕明白吧
函数类型解析
在上面的语法中 (num1: number, num2: number) => void,代表的就是一个函数类型:
接收两个参数的函数:num1 和 num2,并且都是 number 类型
并且这个函数是没有返回值的,所以是 void
在某些语言中,可能参数名称 num1 和 num2 是可以省略,但是 TypeScript 是不可以的:
参数的可选类型
我们可以指定某个参数是可选的
这个时候这个参数 y 依然是有类型的,它是什么类型呢? number | undefined
另外可选类型需要在必传参数的后面:
1 | //不报错 |
默认参数
1 | function print(x: number, y: number = 100) { |
从 ES6 开始,JavaScript 是支持默认参数的,TypeScript 也是支持默认参数的
这个时候 y 的类型其实是 undefined 和 number 类型的联合。
剩余参数
从 ES6 开始,JavaScript 也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。
1 | function sum(...nums: number[]) { |
this 类型
1 | const info = { |
上面的代码是可以正常运行的,也就是 TypeScript 在编译时,认为我们的 this 是可以正确去使用的
TypeScript 认为函数 say 有一个对应的 this 的外部对象 info,所以在使用时,就会把 this 当做该对象。
1 | function foo() { |
强调一下,TypeScript 进行类型检测的目的是让我们的代码更加的安全
- 所以这里对于 foo 的调用来说,我们虽然将其放到了 info 中,通过 info 去调用,this 依然是指向 info 对象的
- 但是对于 TypeScript 编译器来说,这个代码是非常不安全的,因为我们也有可能直接调用函数,或者通过别的对象来调用函数
- 所以这里在编译时会报错,要求我们指定 this 类型
指定 this 的类型
1 | type NameType = { |
函数的重载
TypeScript 中,如果我们编写了一个 add 函数,希望可以对字符串和数字类型进行相加,应该如何编写呢?
我们可能会这样来编写,但是其实是错误的:
那么这个代码应该如何去编写呢?
- 在 TypeScript 中,我们可以去编写不同的重载签名(overload signatures)来表示函数可以以不同的方式进行调用
- 一般是编写两个或者以上的重载签名,再去编写一个通用的函数以及实现
1 | function sum(n1: number, n2: number): number; |
在我们调用 sum 的时候,它会根据我们传入的参数类型来决定执行函数体时,到底执行哪一个函数的重载签名
注意,有实现体的函数,是不能直接被调用的
联合类型和重载
有一个需求:定义一个函数,可以传入字符串或者数组,获取它们的长度。
1 | //联合类型实现 |
开发中我们选择使用哪一种呢?
- 在可能的情况下,尽量选择使用联合类型来实现