TypeScript 基础类型(下):数组、元组与枚举
本文献给已掌握 JavaScript 基础并熟悉 TypeScript 中 string、number、boolean 及类型注解的开发者。本文将系统讲解 TypeScript 中数组、元组与枚举的定义与使用帮助你精准描述更复杂的数据结构。你将学到数组的三种定义方式与类型推断元组的固定长度、可选元素与剩余元素数字枚举、字符串枚举及常量枚举的区别枚举编译后的 JavaScript 产物分析常见错误与最佳实践目录一、数组类型Array1.1 基本定义1.2 数组的类型推断1.3 只读数组1.4 多维数组二、元组Tuple2.1 基本元组2.2 可选元素2.3 剩余元素Rest Elements2.4 只读元组2.5 元组与数组的区别三、枚举Enum3.1 数字枚举3.2 字符串枚举3.3 异构枚举混合3.4 常量枚举const enum3.5 枚举编译产物分析普通数字枚举字符串枚举常量枚举3.6 枚举与字面量联合类型对比四、常见错误与注意事项4.1 数组赋值类型不匹配4.2 元组越界访问4.3 枚举的陷阱数字枚举反向映射污染4.4 常量枚举与 isolatedModules 不兼容4.5 as const 与枚举的选择五、综合示例六、小结一、数组类型Array在 TypeScript 中数组类型有两种等效的写法类型 方括号或泛型Array类型。1.1 基本定义// 方式一类型 []letlist1:number[][1,2,3];letlist2:string[][a,b,c];// 方式二泛型 Array类型letlist3:Arraynumber[1,2,3];letlist4:Arraystring[a,b,c];两种方式完全等价推荐使用类型[]更简洁易读。1.2 数组的类型推断初始化数组时TypeScript 会根据元素类型推断数组类型letarr1[1,2,3];// 推断为 number[]letarr2[hello,ts];// 推断为 string[]letarr3[1,hello];// 推断为 (string | number)[]letarr4[];// 推断为 any[]需谨慎如果数组初始为空后续推入元素也会影响类型推断letarr[];// any[]arr.push(1);// 此时 arr 仍然是 any[]arr.push(a);// 仍然允许// 更好的做法显式注解letarr2:number[][];arr2.push(1);// OKarr2.push(a);// ❌1.3 只读数组有时我们希望数组创建后不可修改可以使用readonly或ReadonlyArrayT。// 方式一readonly 修饰符letroArr:readonlynumber[][1,2,3];roArr[0]10;// ❌ 无法赋值roArr.push(4);// ❌ 属性 push 不存在// 方式二ReadonlyArrayT 泛型letroArr2:ReadonlyArraynumber[1,2,3];// 方式三使用 as const更严格变成字面量只读元组letroArr3[1,2,3]asconst;// roArr3 类型为 readonly [1, 2, 3]提示readonly number[]与ReadonlyArraynumber等价但前者更简洁。1.4 多维数组letmatrix:number[][][[1,2,3],[4,5,6]];letdeep:string[][][][[[a]]];// 三维数组二、元组Tuple元组允许表示一个已知元素数量和类型的数组各元素的类型不必相同。2.1 基本元组lettuple:[string,number][Alice,25];// 类型顺序必须匹配letwrong:[string,number][25,Alice];// ❌访问元素时TypeScript 会正确推断对应位置类型letnametuple[0];// stringletagetuple[1];// number2.2 可选元素在元组中可以使用?标记可选元素可选元素必须位于必选元素之后。lettuple2:[string,number?][Alice];// OKlettuple3:[string,number?][Alice,25];// OKlettuple4:[string,number?][25];// ❌ 第一个必须是 string2.3 剩余元素Rest Elements使用...定义不定长度的元组剩余元素必须是数组类型。// 至少一个 string后面任意多个 numberlettuple5:[string,...number[]][Alice,1,2,3];// 开头任意多个 boolean最后一个是 stringlettuple6:[...boolean[],string][true,false,end];// 混合使用string, 可选 number, 任意多个 booleanlettuple7:[string,number?,...boolean[]][start,true,false];2.4 只读元组letroTuple:readonly[string,number][Alice,25];roTuple[0]Bob;// ❌ 只读属性// 或者使用 as constletroTuple2[Alice,25]asconst;// 类型为 readonly [Alice, 25]2.5 元组与数组的区别特性数组number[]元组[string, number]元素类型全部相同可以不同长度可变固定除剩余元素外常见场景列表、集合固定结构如坐标、键值对三、枚举Enum枚举是 TypeScript 对 JavaScript 的扩展用于定义一组命名常量使代码更易读。3.1 数字枚举数字枚举的成员默认从0开始自增。enumDirection{Up,// 0Down,// 1Left,// 2Right// 3}letdir:DirectionDirection.Up;console.log(dir);// 0可以手动赋值enumStatus{Pending1,Approved,// 2自动递增Rejected// 3}// 部分手动部分自动enumColor{Red1,Green,// 2Blue10,Yellow// 11}数字枚举支持反向映射通过值获取键名enumDirection{Up,Down,Left,Right}console.log(Direction[0]);// Upconsole.log(Direction.Up);// 03.2 字符串枚举字符串枚举的每个成员必须用字符串字面量初始化没有自增行为。enumLogLevel{ErrorERROR,WarnWARN,InfoINFO}letlevel:LogLevelLogLevel.Error;console.log(level);// ERROR字符串枚举不支持反向映射。3.3 异构枚举混合不推荐使用除非有特殊需求。enumMixed{No0,YesYES}3.4 常量枚举const enum常量枚举在编译时会被内联不生成真实的对象代码性能更好。constenumDirection{Up,Down,Left,Right}letmoveDirection.Up;编译后// 编译结果letmove0/* Direction.Up */;常量枚举的限制不能使用反向映射且只能在外部模块中访问如果preserveConstEnums为 false默认如此。3.5 枚举编译产物分析普通数字枚举// TypeScriptenumColor{Red,Green,Blue}编译后的 JavaScript// JavaScriptvarColor;(function(Color){Color[Color[Red]0]Red;Color[Color[Green]1]Green;Color[Color[Blue]2]Blue;})(Color||(Color{}));生成的Color对象同时包含正向映射Color.Red-0和反向映射Color[0]-Red。字符串枚举enumLogLevel{ErrorERROR,WarnWARN}编译后varLogLevel;(function(LogLevel){LogLevel[Error]ERROR;LogLevel[Warn]WARN;})(LogLevel||(LogLevel{}));没有反向映射。常量枚举常量枚举在编译后完全消失所有引用被替换为字面量值。constenumSize{Small1,Large2}letsSize.Small;编译后lets1;// 直接替换为值3.6 枚举与字面量联合类型对比现代 TypeScript 推荐使用字面量联合类型替代简单枚举尤其是字符串枚举。// 枚举方式enumDirection{UpUP,DownDOWN}// 字面量联合类型更轻量无运行时开销typeDirectionUP|DOWN;letdir:DirectionUP;选择建议需要反向映射、自增行为或运行时枚举对象 → 使用数字枚举仅需一组常量字符串且不关心运行时 → 使用字面量联合类型需要将枚举值作为独立类型使用并且不希望产生额外代码 → 使用const enum但注意打包工具兼容性四、常见错误与注意事项4.1 数组赋值类型不匹配letnums:number[][1,2,3];nums[a,b];// ❌ string 不能赋给 number4.2 元组越界访问lettuple:[string,number][Alice,25];letvaltuple[2];// ❌ 长度为 2索引 2 越界4.3 枚举的陷阱数字枚举反向映射污染enumStatus{Active1,Inactive}// 编译后Status 对象额外包含反向映射键可能干扰对象遍历4.4 常量枚举与isolatedModules不兼容在使用ts-loader或babel且开启isolatedModules时常量枚举可能出错。此时需要改用普通枚举或禁用常量枚举。4.5as const与枚举的选择// as const 生成只读元组/对象没有独立类型名constcolors[red,green,blue]asconst;// 类型为 readonly [red, green, blue]// 需要重复使用类型别名时更适合用枚举或字面量联合typeColorred|green|blue;五、综合示例// 定义一个学生元组[姓名, 年龄, 可选性别]typeStudent[string,number,male|female?];// 定义一个班级类classClassRoom{privatestudents:Student[][];addStudent(...student:Student){this.students.push(student);}getAllStudents():Student[]{returnthis.students;}// 枚举用于成绩等级getGrade(score:number):Grade{if(score90)returnGrade.A;if(score75)returnGrade.B;if(score60)returnGrade.C;returnGrade.D;}}// 数字枚举enumGrade{A90,B75,C60,D0}// 使用示例constclassroomnewClassRoom();classroom.addStudent(Alice,20,female);classroom.addStudent(Bob,22);// 性别可选console.log(classroom.getGrade(85));// 输出 75Grade.B// 遍历学生for(const[name,age,gender]ofclassroom.getAllStudents()){console.log(${name},${age}岁${gender?, 性别${gender}:});}六、小结类型语法示例特点数组let arr: number[] [1,2]同类型长度可变只读数组let ro: readonly number[] [1]不可修改元组let t: [string, number] [a,1]固定长度类型可不同可选元组let t: [string, number?] [a]元素可选剩余元组let t: [string, ...number[]]不定长尾部数字枚举enum E { A, B }自动递增支持反向映射字符串枚举enum E { A a, B b }无反向映射常量枚举const enum E { A, B }编译时内联无运行时对象觉得文章有帮助别忘了 点赞 – 给我一点鼓励⭐ 收藏 ⭐– 方便以后查看 关注 – 获取更新通知标签#TypeScript#数组#元组#枚举#学习笔记#前端开发