2026/4/3 21:40:10
网站建设
项目流程
新建设网站如何推广,东莞人才网最新招聘信息,网站logo设计制作,做家常菜哪个网站最好TypeScript学习-第3章#xff1a;复合类型
各位前端工友们#xff0c;上一章咱们搞定了基础类型#xff0c;相当于摸清了TS世界里的“单个零件”——字符串、数字这些独立个体。但实际开发中#xff0c;咱们面对的都是“组装件”#xff1a;比如用户列表是多个用户对象组成…TypeScript学习-第3章复合类型各位前端工友们上一章咱们搞定了基础类型相当于摸清了TS世界里的“单个零件”——字符串、数字这些独立个体。但实际开发中咱们面对的都是“组装件”比如用户列表是多个用户对象组成的集合一条订单信息里既有字符串姓名又有数字金额。这一章咱们就解锁“零件组装技能”——复合类型核心搞定数组、元组、对象这三大主力学会给复杂数据结构“贴精准标签”。如果说基础类型是“单兵作战”那复合类型就是“团队协作”掌握它们才能应对真实业务场景。一、数组类型同类元素的“整齐队列”数组咱们在JS里天天用本质是“一组相同类型的数据集合”。TS给数组加类型约束就是给这个队列定规矩“所有人必须是同一种身份”避免混进“异类”。咱们先讲两种声明方式再聊只读数组的特殊用法。1. 两种声明方式各有适配场景TS里数组有两种标注风格按需选择即可核心效果一致简洁式type[]——日常开发首选写法清爽。在基础类型后面加[]就表示“该类型的数组”。// 数字数组只能存数字 let scores: number[] [90, 85, 95]; // 字符串数组只能存字符串 let names: string[] [张三, 李四, 王五]; // 错误示例混存不同类型会标红 // let mixArr: number[] [10, 20]; // 类型不匹配泛型式Arraytype——基于泛型语法后续章节会深入适合复杂场景如嵌套泛型。写法是Array后跟尖括号里面填元素类型。// 数字数组和number[]等价 let scores: Arraynumber [90, 85, 95]; // 字符串数组和string[]等价 let names: Arraystring [张三, 李四, 王五];小提醒日常开发用type[]就够了只有当数组元素是泛型类型比如后续的ArrayArraynumber二维数组时泛型式会更易读。2. 只读数组不能修改的“固定队列”有些场景下数组创建后就不能增删改元素比如接口返回的固定列表这时候就需要“只读数组”相当于给队列上了“锁”禁止任何修改操作。有两种声明方式readonly type[]——简洁式在类型前加readonly。// 只读字符串数组 let readonlyNames: readonly string[] [张三, 李四]; // 以下操作都会报错只读数组禁止修改 // readonlyNames.push(赵六); // 禁止新增 // readonlyNames[0] 张小三; // 禁止修改元素 // readonlyNames.pop(); // 禁止删除ReadonlyArraytype——泛型式和上面效果完全一致。let readonlyScores: ReadonlyArraynumber [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:stringperson[0];letage:numberperson[1];// 错误示例类型不匹配或长度不一致// let wrongPerson1: [string, number, boolean] [李四, 26, true]; // 第2个类型错误// let wrongPerson2: [string, number, boolean] [李四, 26]; // 长度不足2. 元组的避坑点与实用场景元组看似简单但有两个容易踩的坑还有几个高频实用场景咱们逐一梳理越界赋值的隐患虽然元组长度固定但在非严格模式下用push方法新增元素不会报错严格模式下会警告但新增元素的类型会被约束为元组所有类型的联合类型。let person: [string, number] [张三, 25]; person.push(30); // 非严格模式下不报错新增元素必须是string或number // person.push(true); // 报错布尔值不属于元组类型的联合类型建议用元组就尽量保持“固定长度”避免手动增删元素开启严格模式可减少此类隐患。可选元素TS 4.0支持元组也可以有可选元素用?标记可选元素必须放在最后。// 第3个元素手机号是可选的 let user: [string, number, string?] [张三, 25]; user [李四, 26, 13800138000]; // 也可以补全可选元素实用场景元组适合处理“结构固定的短数据”比如接口返回的坐标[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.phone13800138000;避坑点访问可选属性时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判断三是误以为只读复合类型“内部属性也不可修改”。这些都需要通过实践慢慢磨合。下一章咱们要升级技能学习函数类型的精准约束——给函数的参数、返回值贴标签让函数调用更安全、重构更放心。记得多动手写嵌套场景的代码培养“结构化类型思维”咱们下一章见