当前位置: 首页 > news >正文

TypeScript学习-第3章:复合类型

TypeScript学习-第3章:复合类型

各位前端工友们,上一章咱们搞定了基础类型,相当于摸清了TS世界里的“单个零件”——字符串、数字这些独立个体。但实际开发中,咱们面对的都是“组装件”:比如用户列表是多个用户对象组成的集合,一条订单信息里既有字符串姓名,又有数字金额。

这一章咱们就解锁“零件组装技能”——复合类型,核心搞定数组、元组、对象这三大主力,学会给复杂数据结构“贴精准标签”。如果说基础类型是“单兵作战”,那复合类型就是“团队协作”,掌握它们才能应对真实业务场景。

一、数组类型:同类元素的“整齐队列”

数组咱们在JS里天天用,本质是“一组相同类型的数据集合”。TS给数组加类型约束,就是给这个队列定规矩:“所有人必须是同一种身份”,避免混进“异类”。咱们先讲两种声明方式,再聊只读数组的特殊用法。

1. 两种声明方式:各有适配场景

TS里数组有两种标注风格,按需选择即可,核心效果一致:

  • 简洁式:type[]——日常开发首选,写法清爽。在基础类型后面加[],就表示“该类型的数组”。
    // 数字数组:只能存数字 let scores: number[] = [90, 85, 95]; // 字符串数组:只能存字符串 let names: string[] = ["张三", "李四", "王五"]; // 错误示例:混存不同类型会标红 // let mixArr: number[] = [10, "20"]; // 类型不匹配

  • 泛型式:Array<type>——基于泛型语法(后续章节会深入),适合复杂场景(如嵌套泛型)。写法是Array后跟尖括号,里面填元素类型。
    // 数字数组,和number[]等价 let scores: Array<number> = [90, 85, 95]; // 字符串数组,和string[]等价 let names: Array<string> = ["张三", "李四", "王五"];小提醒:日常开发用type[]就够了,只有当数组元素是泛型类型(比如后续的Array<Array<number>>二维数组)时,泛型式会更易读。

2. 只读数组:不能修改的“固定队列”

有些场景下,数组创建后就不能增删改元素(比如接口返回的固定列表),这时候就需要“只读数组”,相当于给队列上了“锁”,禁止任何修改操作。有两种声明方式:

  • readonly type[]——简洁式,在类型前加readonly
    // 只读字符串数组 let readonlyNames: readonly string[] = ["张三", "李四"]; // 以下操作都会报错:只读数组禁止修改 // readonlyNames.push("赵六"); // 禁止新增 // readonlyNames[0] = "张小三"; // 禁止修改元素 // readonlyNames.pop(); // 禁止删除

  • ReadonlyArray<type>——泛型式,和上面效果完全一致。
    let readonlyScores: ReadonlyArray<number> = [90, 85]; // 同样禁止所有修改操作 // readonlyScores[1] = 90; // 报错

避坑点:只读数组只是“禁止修改元素和长度”,如果元素是对象(引用类型),对象内部的属性仍可修改(后续对象部分会细说)。比如readonly {name: string}[],数组不能增删,但里面对象的name可以改。

二、元组(Tuple):固定“人数”和“身份”的队列

数组是“同类元素的可变长队列”,而元组是“固定长度、固定类型顺序的严格队列”——相当于规定了“队列里必须有n个人,第1个是A身份,第2个是B身份,不能多也不能少”。这种特性特别适合处理“结构固定的短数据”。

1. 元组的基础用法

声明语法:用[类型1, 类型2, ...]列出每个位置的类型,赋值时必须严格对应——长度一致、类型顺序一致。

// 元组:第1个元素是字符串(姓名),第2个是数字(年龄),第3个是布尔(是否成年)letperson:[string,number,boolean]=["张三",25,true];// 正确访问:按索引取对应类型的值letname:string=person[0];letage:number=person[1];// 错误示例:类型不匹配或长度不一致// let wrongPerson1: [string, number, boolean] = ["李四", "26", true]; // 第2个类型错误// let wrongPerson2: [string, number, boolean] = ["李四", 26]; // 长度不足

2. 元组的避坑点与实用场景

元组看似简单,但有两个容易踩的坑,还有几个高频实用场景,咱们逐一梳理:

  1. 越界赋值的隐患:虽然元组长度固定,但在非严格模式下,用push方法新增元素不会报错(严格模式下会警告),但新增元素的类型会被约束为元组所有类型的联合类型。
    let person: [string, number] = ["张三", 25]; person.push(30); // 非严格模式下不报错,新增元素必须是string或number // person.push(true); // 报错:布尔值不属于元组类型的联合类型建议:用元组就尽量保持“固定长度”,避免手动增删元素,开启严格模式可减少此类隐患。

  2. 可选元素(TS 4.0+支持):元组也可以有可选元素,用?标记,可选元素必须放在最后。
    // 第3个元素(手机号)是可选的 let user: [string, number, string?] = ["张三", 25]; user = ["李四", 26, "13800138000"]; // 也可以补全可选元素

  3. 实用场景:元组适合处理“结构固定的短数据”,比如接口返回的坐标([x, y])、用户的账号密码组合、函数返回的多值结果等。
    // 场景1:坐标(x是数字,y是数字) let position: [number, number] = [100, 200]; // 场景2:函数返回多值(成功状态+数据) function getUser(): [boolean, {name: string, age: number}] { return [true, {name: "张三", age: 25}]; }

三、对象类型:多类型元素的“组合体”

对象是TS里最常用的复合类型,本质是“键值对的集合”,每个键对应一个值,值可以是任意类型(基础类型、复合类型都可)。TS给对象加类型约束,就是给每个“键”指定对应的“值类型”,避免乱赋值。

1. 直接声明:快速约束简单对象

对于结构简单的对象,可直接在变量后标注类型,格式为{ 键1: 类型1; 键2: 类型2; ... },多个键值对用分号分隔(逗号也可,习惯用分号更规范)。

// 声明一个用户对象类型:name是字符串,age是数字,isAdult是布尔letuser:{name:string;age:number;isAdult:boolean;}={name:"张三",age:25,isAdult:true};

2. 可选属性:允许“可有可无”的键

实际开发中,有些对象属性不是必填的(比如用户的手机号、邮箱),这时候用?标记为可选属性——赋值时可以省略该属性,也可以补全。

// 手机号(phone)是可选属性letuser:{name:string;age:number;phone?:string;// 可选属性}={name:"张三",age:25// 省略phone属性,不报错};// 也可以补全可选属性user.phone="13800138000";

避坑点:访问可选属性时,TS会提示“可能为undefined”,需要先判断是否存在再使用,避免运行时错误。

// 正确写法:先判断phone是否存在if(user.phone){console.log(user.phone.length);// 不报错}

3. 只读属性:初始化后不能修改的键

有些对象属性初始化后就不能修改(比如用户的ID、订单编号),用readonly标记为只读属性——只能在创建对象时赋值,后续无法修改。

letuser:{readonlyid:number;// 只读属性name:string;}={id:1001,name:"张三"};user.name="张小三";// 可修改// user.id = 1002; // 报错:只读属性不能修改

和只读数组类似:只读属性只是“禁止修改属性值”,如果属性值是对象(引用类型),对象内部的属性仍可修改。

四、实践:复合类型的嵌套玩法

真实业务场景中,复合类型很少单独使用,大多是“嵌套组合”——比如对象数组、元组嵌套对象、对象里包含数组等。咱们结合两个高频场景,实战演练如何标注类型。

场景1:对象数组(最常用)

比如接口返回的用户列表,是“多个用户对象组成的数组”,标注时要先定义单个用户的对象类型,再用数组类型包裹。

// 单个用户的对象类型typeUser={id:number;name:string;age:number;phone?:string;};// 用户列表:User类型的数组letuserList:User[]=[{id:1001,name:"张三",age:25},{id:1002,name:"李四",age:26,phone:"13800138000"},{id:1003,name:"王五",age:24}];// 访问嵌套属性:类型安全有提示console.log(userList[0].name);// 张三(TS自动提示name属性)

场景2:元组嵌套对象

比如处理“用户信息+订单列表”的组合数据,元组第一个元素是用户对象,第二个元素是订单对象数组。

// 订单对象类型typeOrder={orderId:string;amount:number;};// 元组:第1个元素是User对象,第2个是Order数组letuserWithOrders:[User,Order[]]=[{id:1001,name:"张三",age:25},[{orderId:"OD2024001",amount:99},{orderId:"OD2024002",amount:199}]];// 访问嵌套数据console.log(userWithOrders[0].name);// 张三console.log(userWithOrders[1][0].amount);// 99

场景3:对象嵌套数组+可选属性

比如商品信息,包含基础属性和可选的规格数组。

typeProduct={id:number;name:string;price:number;specs?:string[];// 可选的规格数组};letproduct:Product={id:2001,name:"T恤",price:99,specs:["M码","L码","XL码"]};// 可选数组的安全访问if(product.specs){console.log(product.specs.length);// 3}

五、本章小结:复合类型的核心是“结构化约束”

这一章咱们吃透了数组、元组、对象三大复合类型,核心逻辑可以总结为:复合类型是基础类型的“结构化组合”,类型标注的本质是给“组合规则”贴标签——数组定“同类元素的队列规则”,元组定“固定长度和顺序的队列规则”,对象定“键值对的对应规则”。

新手容易踩的坑:一是混淆数组和元组的使用场景(变长用数组,定长用元组);二是忽略可选属性的undefined判断;三是误以为只读复合类型“内部属性也不可修改”。这些都需要通过实践慢慢磨合。

下一章咱们要升级技能,学习函数类型的精准约束——给函数的参数、返回值贴标签,让函数调用更安全、重构更放心。记得多动手写嵌套场景的代码,培养“结构化类型思维”,咱们下一章见!

http://www.cnnetsun.cn/news/859712.html

相关文章:

  • 【AutoCAD二次开发】一键获取CAD块信息!实用技巧大公开
  • 物联网控制面板多设备联动测试:软件测试从业者的实战指南
  • 2026毕设ssm+vue美食推荐系统app论文+程序
  • 嘉立创EDA:自动升级软件下载下来的安装包存放在什么地方
  • SOC一级分析师告警分诊失效:企业网络安全的核心级风险
  • Java springboot基于微信小程序的宠物服务预约系统宠物用品(源码+文档+运行视频+讲解视频)
  • AI写论文有妙招,这4款AI论文写作工具,为你的论文质量保驾护航!
  • ‌AI透明度报告:测试员如何给黑箱模型做X光?‌
  • Claude Code Slash Commands:从“提问者“到“指令设计师“的蜕变
  • AI个人色彩分析工具:发现你的专属色盘
  • 章节 3:K8S 核心组件工作原理(控制平面)
  • Python序列协议深度解析:从抽象类到自定义序列实现
  • 自指AI安全协议草案:为具备自我认知的智能系统建立存在边界V0.1
  • web学习练习题
  • 从隐私合规到地图创新:腾讯地图SDK的隐私协议深度解析与实践指南
  • Qwen3-VL-8B-Instruct-GGUF实操手册:GGUF格式加载速度与显存占用实测
  • 图解说明VDMA工作原理:入门级配置操作指南
  • GTE中文-large部署教程:从start.sh脚本解析到环境变量全局配置最佳实践
  • CogVideoX-2b环境配置:AutoDL镜像一键启动详细步骤
  • 企业级语音方案:GLM-TTS在智能播报中的应用
  • ChatTTS语音样本展示:多种音色种子下的表达差异
  • Nano-Banana工业应用:ISO/IEC标准文档配套插图AI生成流程
  • Qwen1.5-0.5B-Chat量化推理:INT8精度部署实战
  • YOLO X Layout效果展示:手写签名与印刷体Text共存区域的Mask级分离效果
  • BGE-Reranker-v2-m3为何比双塔模型准?交叉编码机制解析
  • MedGemma X-Ray快速上手:基于开源镜像的AI胸片分析系统免编译部署
  • Docker简单服务迁移
  • 触发器的创建和使用:完整指南(零基础适用)
  • 语音情感识别避坑指南:科哥镜像使用常见问题全解
  • bert-base-chinese中文语义匹配实战:招聘JD与简历匹配度打分系统