网站首页 > 技术文章 正文
在学习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的过程又是流畅的。
猜你喜欢
- 2025-05-21 n8n — 可扩展的自动化工作流
- 2025-05-21 可以直接拿来做项目的开源框架
- 2025-05-21 LangFlow技术深度解析:可视化编排LangChain应用的新范式(2)
- 2025-05-21 项目中使用 husky 格式化代码和校验 commit 信息
- 2025-05-21 鸿蒙开发之ArkTS制作显式动画
- 2025-05-21 开发者必备路线图:从此告别技术迷茫
- 2025-05-21 鸿蒙NEXT开发-ArkTS
- 2025-05-21 阮一峰高质量免费 TypeScript 教程,适合有 JS 基础的人系统学习 TS
- 2025-05-21 前端项目自动检测更新并提示用户刷新页面
- 2025-05-21 Rust+Tauri2+React+TS剪切板管理桌面端应用开发示例
你 发表评论:
欢迎- 05-24网络信息安全之敏感信息在传输、显示时如何加密和脱敏处理
- 05-24常见加密方式及Python实现
- 05-24pdf怎么加密
- 05-24aes256 加密 解密 (python3) 「二」
- 05-24深入理解Python3密码学:详解PyCrypto库加密、解密与数字签名
- 05-24Springboot实现对配置文件中的明文密码加密
- 05-24JavaScript常规加密技术
- 05-24信息安全人人平等 谷歌推出低性能安卓手机加密技术
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)