TypeScript中的函数详解

  • Post author:
  • Post category:其他

一、TypeScript函数类型的基本使用

在使用函数的过程中,函数是否也可以有自己的类型。

只需要编写函数类型的表达式(Function Type Expressions),来表示函数类型。

1.1 函数类型的定义

type calcFunType = (num1: number, num2: number) => void

代表定义了一个函数类型,函数要求有两个number类型的参数,并且函数没有返回值

注意点:

官方文档明确强调,函数参数的参数名称不可以省略

1.2 函数作为参数时, 在参数中如何编写类型

type FooFnType = () => void
function bar(fn: FooFnType) {
  fn()
}

代表bar函数需要接收一个无参五返回值的函数

1.3 定义常量时, 编写函数的类型

type AddFnType = (num1: number, num2: number) => number
const add: AddFnType = (a1: number, a2: number) => {
  return a1 + a2
}

明确add变量的类型是一个函数类型

并且此函数类型求有两个number类型的参数,并且函数需要有一个number类型的返回值

二、函数的返回值

2.1 函数有返回值

function sum(num1: number, num2: number):number {
  return num1 + num2
}

这个类型注解出现在函数列表的后面

通常情况下不需要返回类型注解,因为TypeScript会根据 return 返回值推断函数的 返回类型

而某些第三方库处于方便理解,会明确指定返回类型,具体写不写看公司规范

2.2 函数无返回值

void通常用来指定一个函数是没有返回值的,即如果函数没有返回值,那么它的返回值就是void类型。

function sum(num1: number, num2: number): void {
  console.log(num1 + num2)
}

上面声明了一个函数,需要接收两个数字类型参数num1和num2,并且没有返回值。

但是即使不写void,TypeScript也会推断出来这个函数是没有返回值的,开发中习惯上是不写

三、函数参数的可选类型

有时候,函数并不要求每个参数都要去传递,而是可以选择只传一部分参数。

function foo(x: number, y?: number) {

}

y? 就代表y参数是一个可选参数,可以选择不传递

y?: number 等同于组合类型 undefined | number

可选类型是必须写在必选类型的后面的

四、函数参数的默认值

ES6开始,JavaScript是支持默认参数的,TypeScript也是支持默认参数的。

function foo(y: number, x: number = 20) {
  console.log(x, y)
}
foo(30)

当参数x不传时,x的默认值就是20

这个时候x的类型其实是 undefined 和 number 类型的联合类型

注意点:

函数各类型参数的编写位置

先写必传参数 - 然后写有默认值的参数 - 最后写可选参数

五、函数的剩余参数

ES6开始,JavaScript也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中。

function sum(initalNum: number, ...nums: number[]) {
  let total = initalNum
  for (const num of nums) {
    total += num
  }
  return total
}

console.log(sum(20, 30))
console.log(sum(20, 30, 40))

...nums: number[]相当于可以传入任意类型的参数

它们会被封装到nums这个数组当中

六、this的默认推导类型

因为this在不同的情况下会绑定不同的值,TypeScript是如何处理this呢?

6.1 this可以被推导出来的情况

const info = {
  eating() {
    console.log("eating...")
  }
}

info.eating()

这种情况下,this是可以被推导出来,eating()函数的调用者info对象就是TypeScript推导出来的this

6.2 this不能被推导出来的情况

function eating() {
  console.log("eating...")
}

const info = {
  eating
}

info.eating()

这段代码运行将会报错。

TypeScript进行类型检测的目的是让我们的代码更加的安全;

所以这里对于eating的调用来说,虽然将其放到了info中,通过info去调用,this依然是指向info对象。

对于TypeScript编译器来说,这样是非常不安全的。因为我们可能直接调用函数,或者通过对象来 调用函数。

6.3 手动指定this的类型

当遇到this不能被推导出来的时候,通常TypeScript会要求我们明确的指定函数中this的类型。

1)指定一个没有属性的this类型

type thisType = {}			// 定义this类型为一个没有属性的对象	

function eating(this: thisType, message: string) {	// 指定该函数的this类型	
  console.log("eating", message)					
}

const info = {
  eating: eating
};

// 隐式绑定
info.eating("food")			//info对象要满足thisType约定的对象类型,才可以去调用eating方法

2)指定一个有属性的this类型

type ThisType = { name: string };	// 定义this类型为一个只有name属性的对象	

function eating(this: ThisType, message: string) {	// 指定该函数的this类型	
  console.log(this.name + " eating", message);
}

const info = {
  name: 'zs'
  eating: eating,
};

// 隐式绑定
info.eating("food");	// info对象要满足thisType约定的对象类型,即拥有一个字符串类型的name属性 
						// 才可以去调用eating方法

3)显示绑定

type ThisType = { name: string };	// 定义this类型为一个只有name属性的对象	

function eating(this: ThisType, message: string) {	// 指定该函数的this类型	
  console.log(this.name + " eating", message);
}

const info = {
  name: 'zs'
  eating: eating,
};

// 显示绑定
eating.call({name: "ls"}, "food") 		// 手动指定this指定的对象是谁
eating.apply({name: "zl"}, "food")

七、函数的重载

ts中,可以去编写不同的重载签名(overload signatures)表示函数可以以不同的方式进行调用。

一般是编写两个或者以上的重载签名,再去编写一个通用的函数以及实现。

// 定义函数重载签名
function add(num1: number, num2: number): number; 	// 没函数体,没有具体实现
function add(num1: string, num2: string): string;

// 具体的重载函数实现
function add(num1: any, num2: any): any {
  if (typeof num1 === 'string' && typeof num2 === 'string') {
    return num1.length + num2.length
  }
  return num1 + num2
}

console.log(add(30, 30))			// 两个数值类型,会调用参数和返回值都是number的重载
console.log(add("abc", "def"))		// 两个字符串类型,会调用参数和返回值都是string的重载

函数重载的特点:

  • 函数名称相同,但是参数不同的几个函数,就是函数重载

  • 参数不同:参数的个数不同,或者参数的类型不同,都称为参数不同

有实现体的函数,是不能直接被调用的:

比如对于上面的add函数,直接像下面这样子去调用时不行的。

add(20, "30")

因为调用sum函数会在重载签名中从上到下依次匹配,都没有匹配到,就会报错,并不会执行重载函数的实现函数。


版权声明:本文为qq_44749491原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。