web前端开发:Ts中的函数类型

在学习TypeScript的过程中,我们能清晰感受到它与JavaScript的区别,其中类型定义带来的严谨和规范,能提高代码的阅读性和可维护性。那对于js开发者最常用的函数,又该如何去定义,本文将介绍ts中的函数类型定义。

一、函数类型

1. 函数类型的定义:

在使用TypeScript时,我们创建函数要明确两个点:

  • 确定参数的类型
  • 确定返回值的类型

通过函数声明创建函数:

function fn (num : number) : void {

console.log(num)

}

我们在调用函数时能得到函数的类型提示,提示我们需要什么类型的参数,返回值是什么类型:

 

通过函数表达式创建函数:

const fn = function(num : number) : void {

console.log(num)

}

同样,我们先来看下变量fn的类型:

 

相比前者,函数表达式的写法可以增加阅读体验,例如我们用type关键字,将函数类型提取出来:

type FnType = (num: number) => void

const fn : FnType = (num) => {

console.log(num);

}

那当我们在使用函数‘fn’时,得到的提示应该是类型‘FnType’为主:

 

将定义好的函数类型规范‘fn’变量,我们在赋值时无需再书写函数参数以及函数返回值的类型,typescript会对赋值内容进行自动推导再将两者对比。

 

2. 可选参数与默认参数:

  • 可选参数:

我们先看一个案例:

function fn(a, b){

// 如果调用fn时有传入b,则进行b的打印

if(b !== 'undefined') console.log(b)

console.log(a)

}

在JavaScript中,我们定义好一个函数的参数是用于哪块逻辑,在调用函数时,如果参数没传入,默认是传undefined。

但在Ts中,函数类型的定义,必须对每个参数的类型进行定义,而面对这种非必选的参数,需要通过"?"符号进行标记:

// 函数声明

function fn(a: number, b?: string) : void {

if (b !== 'undefined') console.log(b)

console.log(a)

}

// 函数表达式

type FnType = (a: number, b?: string) => void

const fn: FnType = (a, b) => {

if (b !== 'undefined') console.log(b)

console.log(a)

}

可选参数必须在必填参数后,否则不符逻辑,会得到对应的错误提示:

 

  • 默认参数:

为什么要将可选参数和默认参数区分开来?主要是在写法上容易混淆,我们先看下函数表达式的写法:

function fn(a: number, b = '1') : void {

if (b !== 'undefined') console.log(b)

console.log(a)

}

接着我们可以看下typescript编译器对fn类型的提示:

 

在函数声明中,参数给予默认值后无需再写类型,默认值的类型为参数类型,且这个参数为可选参数。

接下来是函数表达式对默认参数的书写,类型的定义书写可选,而函数的定义书写默认值:

type FnType = (a: number, b?: string) => void

const fn: FnType = (a, b = '1') => {

if (b !== 'undefined') console.log(b)

console.log(a)

}

这里不难理解,我们对fn进行类型定义,要求的是第二个参数为可选。

赋值给fn的匿名函数,在进行类型推导时,认定第二个携带默认值的参数为可选参数,符合fn变量类型的要求。

3. 剩余参数的获取:

我们复习一下js中的argument,我们可以通过arguments获取传入的所有参数,其中包括我们没有定义接收的参数:

function fn(a, b){

console.log(arguments);

}

fn(1,2,3,4) // arguments : {'0':1,'1':2,'2':3,'3':4}

在ts中,我们定义函数接收多少个参数后,无法传入更多的参数:

 

我们可以回忆一下,在ES6中对多余参数的收集:

function fn(a, b, ...rest){

console.log(rest) // [ 3, 4 ]

}

fn(1,2,3,4)

同理,在ts中,我们需要对剩余参数进行类型定义,确定剩余参数的类型。

 

4. 关于this的类型定义:

在js中,this的指向是一个重要知识点,在ES6之前,普通函数的this指向只能在调用时确定,其中包括this的指向丢失,call、apply、bind对this指向的改变等;在ES6学习箭头函数后,this的指向可以在函数定义时确定,箭头函数的this指向函数所在的执行上下文。

那在严谨的逻辑中,一个函数的定义应该清晰。

  • 函数的参数(需要什么参数,参数的数据类型)。
  • 函数的作用(返回什么类型的数据,或者是没有返回值)。
  • 函数服务的目标(this的指向)。

我们先看一个情景前提:

const example = {

num: 1,

getNum() {

console.log(this.num);

}

}

const fn = example.getNum

fn() //undefined, this => window

这是最常见的一种场景,getNum函数定义的目的是打印example中的num属性,在赋值过程中,this隐式丢失,导致函数调用时指向window。

没错,可能有同学认为,函数的功能既然能打印example的num属性,也可以打印window的num属性,那取出来也没什么问题,甚至我们可以通过call来指向我们想取出num属性的目标:

example.getNum.call(otherTarget) // otherTarget.num

但如果我这个函数,取出的num属性有类型要求,用于后续逻辑,其他目标的num属性类型是否符合我后续逻辑的要求?

const example = {

num: {a : 1},

getNum() {

console.log(this.num.a.b);

}

}

// 错误使用

const otherTarget = {

num : '111'

}

example.getNum.call(otherTarget) // error

所以我们必须明确函数服务的目标,以免误用导致逻辑错误。

那在ts中,如果明确了函数服务的目标,也就是getNum函数服务于example对象,我们可以对this进行类型定义:

interface Example {

num : number,

getNum : (this : Example) => void

}

const example : Example = {

num: 1,

getNum() {

console.log(this.num);

}

}

定义好函数服务的目标后,我们可以再对比同一段逻辑的使用过程:

 

5. 函数重载(Overloads):

在js中定义一个函数,我们可以通过判断用户传入的类型来决定执行哪一点逻辑:

function fn (target) {

if(typeof target === 'string') return '1'

else return 1

}

fn('1') //return '1'

console.log(fn(1)) // return 1

在ts中,我们需要进行参数的类型定义,还需要确定返回值的定义:

function fn (target: number | string): string | number {

if(typeof target === 'string') return '1'

else return 1

}

但是这种写法得到的返回值会是什么提示呢:

 

如图所示,我们声明的变量f在接受返回值后的得到的类型提示却是字符串和数值的联合类型,不符合我们设计的目的。

函数重载则符合我们设计函数的书写要求:

function fn (target:number) : number

function fn (target:string) : string

function fn (target: number | string): string | number {

if(typeof target === 'string') return '1'

else return 1

}

重载用于记录不同的组合列表,我们在调用函数时,会去进行列表的匹配,由此确定调用者是使用函数的哪一段逻辑,返回什么类型的数据。

总结

在文章中我们学习函数的类型定义,在创建函数时需要确定函数的参数类型和返回值类型,声明函数和函数表达式如何定义,可选参数和默认参数的定义,剩余参数的定义,this的类型定义以及函数重载。相比js中函数的书写,ts的学习成本相对较高,但是从js过渡到ts的过程又是流畅的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值