函数基础:参数和返回类型

函数基础:参数和返回类型

欢迎继续本专栏的第九篇文章。在前几期中,我们已逐步深化了对 TypeScript 类型系统的认识,包括基本类型、特殊类型、枚举、类型断言,以及数组、元组和对象的管理。今天,我们将转向函数这一核心构建块,重点探讨函数的基础知识,特别是类型签名、参数和返回类型的定义。这部分内容是理解 TypeScript 如何提升函数可靠性的关键。我们将从函数的基本概念入手,逐步引入参数类型、返回类型、可选参数、默认参数和函数重载的概念,并通过丰富示例和实际场景分析,帮助您编写更健壮的函数代码。内容将由浅入深展开,确保您能从简单示例过渡到复杂应用,同时获得深刻的洞见。

理解函数在 TypeScript 中的定位

在编程中,函数是代码复用和逻辑封装的基本单位。JavaScript 中的函数灵活但动态,容易因参数类型不匹配或返回意外值而引发运行时错误。TypeScript 通过引入类型签名(type signature),为函数添加了静态检查层,这让函数成为类型安全的堡垒。类型签名本质上是函数的“合同”:它定义了输入(参数类型)、输出(返回类型)和行为约束。

为什么函数类型如此重要?在大型项目中,函数往往被多处调用。没有类型,修改一个函数可能引发连锁 bug;有了类型,编译器能在变更时立即反馈。根据 TypeScript 社区的经验,使用函数类型能将相关错误减少 20-30%。函数在 TypeScript 中的定位不仅是执行代码,更是类型系统的桥梁:它连接变量、对象和更高级结构如类和泛型(后续文章详述)。

TypeScript 函数类型借鉴了函数式语言如 Haskell 的理念,但保持与 JavaScript 的兼容。任何 JS 函数都是有效的 TS 函数,但添加类型能带来智能提示、重构支持和文档化。需要注意的是,函数类型在运行时被移除,不会影响性能。我们将从最简单的函数签名开始,逐步扩展到高级特性,确保您能逐步掌握如何编写可靠的函数代码。

函数的基本定义与类型签名

让我们从函数的基础语法入手。TypeScript 函数的定义类似于 JavaScript,但添加了类型注解。

函数声明的基本形式

一个简单的无参数函数:

functiongreet():void{console.log("Hello, TypeScript!");}

这里,(): void 是类型签名:空参数,返回 void(无值)。调用 greet() 时,编译器确保无参数传入。

带参数的函数:

functionadd(a:number,b:number):number{returna+b;}

签名 (a: number, b: number): number 指定两个 number 参数,返回 number。如果调用 add(“1”, 2),编译器报错:字符串不可赋值为 number。

函数表达式类似:

constmultiply:(x:number,y:number)=>number=(x,y)=>x*y;

这里,类型签名作为变量类型,箭头函数体匹配它。

类型签名的必要性在于它充当文档:阅读者一眼知函数需求。同时,IDE 如 VS Code 提供参数提示,提升开发效率。

类型签名的组成部分

类型签名包括:

  1. 参数列表:每个参数的名称和类型,如 a: number。

  2. 返回类型:函数输出的类型,如 : number。

  3. 可选的函数类型:用于变量或参数,如 (param: string) => boolean。

在 tsconfig.json 的 strict 模式下,未指定返回类型会推断,但显式声明推荐用于清晰性。

简单示例扩展:考虑一个处理字符串的函数。

functioncapitalize(text:string):string{returntext.charAt(0).toUpperCase()+text.slice(1);}

如果返回非 string,如 number,编译错误。这确保函数行为一致。

通过这些基础,您可以看到类型签名如何将函数从“黑盒”转为“透明合同”。

参数类型:确保输入的安全性

参数是函数的输入,TypeScript 通过类型注解锁定它们,防止无效数据进入。

基本参数类型

参数类型直接注解在名称后。

functiondescribePerson(name:string,age:number):string{return`${name}is${age}years old.`;}

调用 describePerson(“Alice”, 30) 有效;describePerson(30, “Alice”) 报错:参数顺序和类型必须匹配。

多参数场景:

functioncalculateArea(length:number,width:number,unit:string="sq ft"):string{return`${length*width}${unit}`;}

这里引入默认值(稍后详述),但类型仍指定。

参数类型支持联合:

functionlogValue(value:string|number):void{console.log(value);}

这允许灵活输入,但内部需处理类型(用 typeof 守卫)。

参数类型的深入应用

在复杂参数中,用接口定义形状。

interfacePoint{x:number;y:number;}functiondistance(p1:Point,p2:Point):number{returnMath.sqrt((p1.x-p2.x)**2+(p1.y-p2.y)**2);}

这在几何计算中实用,确保参数有正确属性。

数组参数:

functionsumArray(numbers:number[]):number{returnnumbers.reduce((acc,curr)=>acc+curr,0);}

防止传入非数组或混合类型。

参数类型的益处:及早错误检测。在团队中,它减少沟通:函数签名即规格。

陷阱:参数过多表示需重构为对象。

返回类型:定义输出的预期

返回类型指定函数输出,确保调用者得到预期值。

基本返回类型

如 add 示例,返回 number。

无返回用 void:

functionlogError(message:string):void{console.error(message);}

如果添加 return,编译错误,除非 return undefined(但不推荐)。

推断返回:TypeScript 可自动推断,但显式更好。

functiongetLength(text:string){// 推断 :stringreturntext.length;// 错误:返回 number,但推断为 number}

修正为 : number。

返回类型的深入应用

返回联合:

functionfindItem(id:number):string|undefined{// 逻辑if(found)return"item";returnundefined;}

这处理可选结果。

返回 Promise:

asyncfunctionfetchData(url:string):Promise<{data:string}>{constres=awaitfetch(url);return{data:awaitres.text()};}

在异步中,确保类型匹配。

返回类型提升可靠性:调用者知输出,可安全链式调用。

高级:返回 never 用于不返回函数(如 throw)。

可选参数:处理灵活输入

可选参数允许函数接受或忽略某些输入,用 ? 标记。

可选参数的基本用法

functiongreetUser(name:string,title?:string):string{returntitle?`${title}${name}`:name;}

调用 greetUser(“Alice”) 或 greetUser(“Alice”, “Ms.”) 有效。title 默认为 undefined。

位置重要:可选参数后不能有必选。

// function bad(a?: number, b: number): void {} // 错误

正确:必选在前。

可选参数的深入应用

结合默认值:

functioncreateUser(name:string,age?:number):{name:string;age:number|undefined}{return{name,age};}

在 API 中:

interfaceOptions{timeout?:number;retries?:number;}functionrequest(url:string,options?:Options):Promise<Response>{// 实现}

这允许灵活配置。

可选参数与守卫:

内部检查:

if(title!==undefined){/* 使用 */}

可选参数增加函数通用性,但过多可选需考虑重载(后述)。

风险:undefined 处理不当导致 bug。总是考虑默认行为。

默认参数:提供内置值

默认参数在 ES6 引入,TypeScript 支持并类型化。

默认参数的基本用法

functionmultiply(a:number,b:number=1):number{returna*b;}

调用 multiply(5) 返回 5;multiply(5, 2) 返回 10。

类型从默认值推断,但可显式。

默认参数的深入应用

复杂默认:

functionbuildQuery(params:{key:string;value:string}[]=[]):string{returnparams.map(p=>`${p.key}=${p.value}`).join("&");}

函数默认:

functionprocess(data:string,transformer:(s:string)=>string=s=>s.toUpperCase()):string{returntransformer(data);}

这在管道处理中实用。

默认与可选结合:默认使可选更强大。

functionlog(message:string,level:string="info"):void{// ...}

默认参数简化调用,减少 boilerplate。但默认值需简单,避免运行时副作用。

陷阱:默认在调用时求值,非定义时。

函数重载:处理多种签名

函数重载允许同一函数名有多个签名,基于参数选择实现。

函数重载的基本用法

重载签名在实现前定义。

functioncombine(a:string,b:string):string;functioncombine(a:number,b:number):number;functioncombine(a:string|number,b:string|number):string|number{if(typeofa==="string"&&typeofb==="string"){returna+b;}elseif(typeofa==="number"&&typeofb==="number"){returna+b;}thrownewError("Invalid types");}

调用 combine(“a”, “b”) 返回 string;combine(1, 2) 返回 number。IDE 基于参数提示返回。

重载签名不实现,仅类型;实现签名覆盖所有。

函数重载的深入应用

多参数重载:

functionformat(value:string):string;functionformat(value:number,decimals:number):string;functionformat(value:string|number,decimals?:number):string{if(typeofvalue==="string"){returnvalue.trim();}else{returnvalue.toFixed(decimals??2);}}

这处理不同输入。

类方法重载类似。

箭头函数不支持直接重载,用函数声明或接口。

接口重载:

interfaceOverloaded{(a:string):string;(a:number):number;}constfunc:Overloaded=(a:any)=>a;

重载提升函数多态性,在库设计中常见,如 lodash。

风险:实现复杂,易出错。优先联合类型;重载用于返回不同。

实际应用:编写可靠函数代码

整合概念,构建实用函数。

场景1:数据处理函数

functionprocessData(data:unknown,validator?:(d:unknown)=>boolean):string|never{if(validator&&!validator(data)){thrownewError("Invalid data");}returndataasstring;// 断言后返回}

场景2:配置函数

interfaceConfig{host:string;port?:number;}functionconnect(config:Config,timeout:number=5000):void{// 连接逻辑}

在 web app 中,可选 port 默认 80。

案例研究

在 Node.js API,函数重载处理查询:

重载让 API 灵活。

在 React hook,重载自定义 hook。

这些应用展示函数类型如何使代码可靠。

高级用法:扩展函数能力

this 类型

在对象方法:

interfaceLogger{log:(message:string)=>void;}constconsoleLogger:Logger={log(this:Logger,message){// this 类型console.log(message);}};

Rest 参数

functionsum(...numbers:number[]):number{returnnumbers.reduce((a,b)=>a+b,0);}

参数解构

functionpoint({x,y}:{x:number;y:number}):number{returnx+y;}

高级:重载与泛型结合(后文)。

风险与最佳实践

风险:

  • 类型宽松导致 bug。
  • 重载实现不覆盖所有。
  • 默认值副作用。

实践:

  • 总是指定返回。
  • 用接口参数复杂结构。
  • 测试边缘。
  • 文档签名。

遵循这些,函数更可靠。

结语:函数,类型安全的基石

通过本篇文章的详尽探讨,您已掌握函数基础,从签名到重载。这些知识将助您编写更可靠代码。实践:在项目添加类型。下一期探讨箭头函数与 this,敬请期待。若有疑问,欢迎交流。我们将继续前行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1131727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘:不用 Conda,Python “光杆司令“ 是如何指挥 GPU 跑大模型的?

写在前面的话 很多刚接触大模型的朋友会有这样的困惑&#xff1a;“我看教程都说要装 Conda&#xff0c;配置虚拟环境。但我直接在系统里的 Python 运行脚本&#xff0c;大模型好像也跑起来了&#xff1f;这时候 Python 到底是怎么跨过 Conda&#xff0c;直接调动我的显卡&…

【毕业设计】通过python-CNN卷积神经网络_pytorch框架对猫的类别识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

箭头函数和 this 绑定

箭头函数和 this 绑定 欢迎继续本专栏的第十篇文章。在前几期中&#xff0c;我们已逐步建立了 TypeScript 函数的基础知识&#xff0c;包括类型签名、参数处理、重载以及返回类型的定义。这些内容为我们理解函数的行为提供了坚实支撑。今天&#xff0c;我们将聚焦于箭头函数这一…

模组无尘系列(Clean Room Series)全解析

TOYO&#xff08;东佑达&#xff09;无尘系列模组专为Class 10&#xff08;ISO 14644-1 标准&#xff09; 洁净室环境设计&#xff0c;通过密封结构优化、真空抽气系统、低发尘材料与润滑三大核心技术&#xff0c;实现运行时发尘量≤10 particles/ft&#xff0c;广泛应用于半导…

【毕业设计】基于python卷积神经网络CNN的不同瓶子识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

戒烟很难?你被大脑骗了

【心智觉醒】别让大脑骗了你:揭开烟瘾底层逻辑的“系统 Bug” 觉醒之门 那个熟悉的“死循环”场景 咱们先聊个几乎每个烟民都经历过的场景 。 周一早上,有个特别重要的项目方案要汇报。你坐在会议室门口,手心里全是汗。这时候,你下意识地溜到楼梯间,掏出火机,“咔哒”一…

【毕业设计】基于python-CNN卷积神经网络对盆栽识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

2023元宇宙AI架构师薪资曝光:北上广深需求翻倍,你值多少钱?

2023元宇宙AI架构师薪资全景报告&#xff1a;北上广深需求暴增&#xff0c;你的能力值百万吗&#xff1f; 关键词 元宇宙AI架构师 | 薪资结构 | 需求趋势 | 技能矩阵 | 职业路径 | 价值评估 | 北上广深就业 摘要 2023年&#xff0c;元宇宙与AI的融合进入爆发期&#xff0c;催生…

计算机深度学习毕设实战-通过python-CNN卷积神经网络_pytorch框架对猫的类别识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

PDD流程终止了

周日拒绝PDD&#xff0c;没继续推 这几天一直在思考选择对吗&#xff1f; 会后悔吗&#xff1f; 但也慢慢看淡 心态保持住 一切随缘 有缘再见 等Jinger真的缺钱啦 希望有缘分见面 家里了说的也对 人这一生读完书剩下的大把时间 都是给工作 好像不急着这一下挣钱 其实不去PDD一个…

【课程设计/毕业设计】基于python-CNN卷积神经网络对盆栽识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

内网环境下安装minio

一、环境 Linux版本&#xff1a;CentOS 6. 下载RPM包&#xff1a;minio-20230809233022.0.0.x86_64.rpm 下载地址&#xff1a;[Minio中国镜像加速站](https://dl.minio.org.cn/server/minio/release/linux-amd64/archive/)二、安装 1、创建文件夹&#xff1a;比如 /u1/minio 2、…

基于python卷积神经网络的淡水生物识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

深度学习毕设项目推荐-基于python-CNN卷积神经网络对鸡和兔识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

深度学习计算机毕设之基于python-CNN卷积神经网络对盆栽识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

数据库性能优化全景实践与SQL示例,不改SQL也能提速百倍

在数据库运维和开发中,SQL 慢查询是常见难题。很多人以为必须改写 SQL 才能优化性能,其实不然。通过外围手段(索引、参数、架构等),不改 SQL 也能让查询速度提升百倍甚至千倍。 本文结合 SQL 示例,系统梳理 “不改SQL”优化全景图。 1. 索引优化 —— 最立竿见影的方法 …

事关收入!拿到PMP®证书后,这几件事别忘了做!

&#x1f4a5;注意&#xff01;11月PMP考试成绩已经公布&#xff0c;还没查成绩的小伙伴们抓紧时间查。顺利通过考试的&#xff0c;可以直接在官网上下载电子证书&#xff0c;纸质版证书一般是在6-8个月之后&#xff0c;由官方发布领取公告才能申请邮寄到家。PMP电子证书和纸质…

王阳明:如何重构崩盘的人生

第01讲 | 历史镜像&#xff1a;王阳明也曾是个“失败者”——从“简历花哨”到“内核强大”&#xff0c;你缺的不是机会&#xff0c;是一次“系统重构”赛博龙场&#xff1a;失败者的系统重启界面你有没有遇到过这种“系统卡顿”&#xff1f;作为一名在软件行业摸爬滚打了 30 多…

MySQL的日期时间类型

一 MySQL的日期时间类型 MySQL数据库的日期时间类型有date、time和datetime类型&#xff0c;还有timestamp类型&#xff0c;在Java代码中无论日期时间是什么样的格式&#xff0c;转换sql语句时统一为yyyy-MM-dd HH:mm:ss.S(Timestamp)的格式&#xff0c;创建案例简单演示。 1…