本文将详细介绍TypeScript中的映射类型。阅读本文后,您将学习到以下知识点:数学中的映射和TS中映射类型之间的关系;映射类型在TS中的应用;映射类型修饰符在TS中的应用;接下来,我们将从“数学中的映射”开始。本文使用的TypeScript版本为v4.6.2。如果对TypeScript不熟悉,可以阅读以下资料:不可多得的TS学习指南(1.8W字)很棒的TypeScript入门教程1.什么是映射?在学习TypeScript类型系统的时候,尽量从数学中的集合类比中学习,比如TypeScript中的union类型,类似于数学中的union等。在数学中,映射指的是元素之间的关系两组相互对应的元素,比如下图:(来源:https://baike.baidu.com/item/%E6%98%A0%E5%B0%84/20402621)映射可以理解为一个函数,如上图所示,当我们需要将集合A的元素转换为集合B的元素时,我们可以使用f函数来映射,例如集合A对应的元素1映射到集合B中的元素2.这样就可以很好的实现映射过程的复用。2.TypeScript中的映射类型是什么?一、概念介绍TypeScript中的映射类型类似于数学中的映射,可以将一个集合的元素转换为一个新集合的元素,但TypeScript映射类型是将一种类型映射到另一种类型。在我们实际开发中,经常需要将一个类型的所有属性都转换为可选类型。这时候可以直接使用TypeScript中的Partial工具类型:typeUser={name:string;位置:字符串;age:number;}typeUser2=Partial;/*User2的类型:typeUser2={name?:string|不明确的;位置?:字符串|不明确的;年龄?:数字|映射到User2类型,并将User类型中的所有属性转换为可选类型。2.实现方法TypeScript映射类型的语法如下:typeTypeName={[PropertyinkeyofType]:boolean;};既然我们可以使用Partial工具类型将指定类型的所有属性都转换为可选类型,那么它的内容原理是什么?我们可以将鼠标悬停在编辑器中的Partial名称上,可以看到编辑器提示如下:Disassembleofiteachpart:typePartial:defineatypealiasPartialandgenericT;keyofT:通过keyof运算符获取泛型T中的所有key,返回一个联合类型(如果不知道什么是联合类型,可以理解为数组);输入User={名称:字符串;位置:字符串;age:number;}typeKeyOfUser=keyofUser;//“名称”|“位置”|"age"in:类似于JS中的ininfor...in,用于遍历目标类型的公共属性名;T[P]:一个索引访问类型(也称为查找类型),获取泛型T中的P类型,类似于JS中访问对象的方式;?:将类型值设置为可选类型;{[PinkeyofT]?:T[P]|undefined}:遍历keyofT返回的union类型,定义为P变量接收,每次遍历返回的值为可选类型T[P]。这样就实现了Partial工具类型。这个操作方法非常重要,是后面TypeScript类型体操的重要基础。关于类型体操的练习,有兴趣的可以看这篇文章:《这 30 道 TS 练习题,你能答对几道?》https://juejin.cn/post/70090466403087810633.类型映射的应用TypeScript映射类型常用于复用一些操作types,比如TypeScript目前支持21种工具类型,我们常用的一些类型操作都定义为这些工具类型,方便开发者复用这些类型。所有支持的工具类型都可以在官方文档中找到:https://www.typescriptlang.org/docs/handbook/utility-types.html我们挑几个常用的工具类型,看看它们在实现过程中是如何使用的类型映射。在学习TypeScript的过程中,建议在官方Playground:https://www.typescriptlang.org/zh/play1多多练习和学习。Required属性用于将类型的所有属性设置为必需属性。实现如下:typeRequired={[PinkeyofT]-?:T[P];};用法:键入User={name?:string;位置?:字符串;age?:number;}typeUser2=Required;/*typeUser2={name:string;位置:字符串;年龄:数字;}*/constuser:User2={name:'pingan8787',age:18}/*error:Property'location'ismissingintype'{name:string;年龄:数字;}'但在类型'Required'中是必需的。*/-?这里的symbol可以暂时理解为“将可选属性转换为必选属性”,下一节将详细介绍这些符号。2.Readonly只读属性用于设置所有属性的类型为只读类型,即类型不能被重新赋值。实现如下:typeReadonly={readonly[PinkeyofT]:T[P];}Usage:typeUser={name?:string;位置?:字符串;age?:number;}typeUser2=Readonly;/*typeUser2={readonlyname?:string|不明确的;只读位置?:字符串|不明确的;只读年龄?:数字|不明确的;}*/constuser:User2={name:'pingan8787',age:18}user.age=20;/*错误:无法分配给'age',因为它是只读属性。*/3。PickSelectthespecifiedproperty从指定的类型中选择指定的属性并返回。实现如下:typePick={[PinK]:T[P];}用法如下:typeUser={name?:string;位置?:字符串;age?:number;}typeUser2=Pick;/*typeUser2={name?:string|不明确的;年龄?:数字|不明确的;}*/constuser1:User2={name:'pingan8787',age:18}constuser2:User2={name:'pingan8787',location:'xiamen',//errorage:18}/*errortype'{名称:字符串;位置:字符串;年龄:数字;}'不可分配给类型'User2'。对象字面量只能指定已知属性,并且类型“User2”中不存在“location”。*/4。Omit忽略指定的属性。忽略指定的属性并返回。实现如下:typeOmit={[PinExclude]:T[P];}Usage:typeUser={name?:string;地点?:细绳;age?:number;}typeUser2=Omit;/*typeUser2={location?:string|不明确的;}*/constuser1:User2={location:'xiamen',}constuser2:User2={name:'pingan8787',//errorlocation:'xiamen'}/*error:Type'{name:string;位置:字符串;}'不可分配给类型'User2'。对象字面量只能指定已知属性,并且类型“User2”中不存在“名称”。*/5。ExcludeExcludethespecifiedtypefromthejointtype从指定的关节类型中排除指定的类型。实现如下:typeExclude=TextendsU?从不:T;用法:类型User={name?:string;位置?:字符串;age?:number;}typeUser2=Exclude;/*typeUser2="location"|“年龄”*/constuser1:User2='年龄';constuser2:User2='位置';constuser3:User2='姓名';//报错/*Error:Type'"name"'isnotassignabletotype'User2'.*/四、映射修饰符的应用在自定义映射类型的时候,我们可以使用两种映射类型修饰符来实现我们的需求:readonly修饰符:设置指定属性为只读类型;?修饰符:将指定的属性设置为可选类型;在介绍Readonly和Partial工具类型时使用过:typeReadonly={readonly[PinkeyofT]:T[P];}typePartial={[PinkeyofT]?:T[P]|undefined;}当然你也可以对修饰符进行操作:+添加修饰符(默认使用);-删除修改器;例如:typeRequired={[PinkeyofT]-?:T[P];//通过-删除?修饰符};也可以用在前面:typeNoReadonly={-readonly[PinkeyofT]:T[P];//Pass-deletethereadonlymodifier}5.Summary本文以数学中的映射为出发点,详细介绍了TypeScript映射类型(MappedType),同时介绍了映射类型的应用和修饰符的应用。在学习TypeScript类型系统的时候,尽量从数学中的集合类比中学习,比如TypeScript中的union类型,类似于数学中的union等。学好映射类型是做事的一个很重要的基础类型体操~~参考TypeScript文档-映射类型:https://www.typescriptlang.org/docs/handbook/2/mapped-types.htmlTypeScript工具类型:https://www.typescriptlang.org/docs/handbook/utility-types.html