当前位置: 首页 > Web前端 > HTML

JSON对象转换TypeScript声明

时间:2023-03-28 16:01:41 HTML

TypeScript介绍TypeScript(TS)是一种强类型编程语言,被前端团队广泛使用,因为可以在编译时发现代码中的问题。TS让开发者掌握各个组件的交互,让代码重构更容易;但是对于需要精确定义的类型,使用起来会比较麻烦。尤其是涉及到几个或几十个后端接口数据的类型定义,会有大量的转换和时间成本。通过VSCode插件一键生成TS声明,可以节省编程过程中的开发成本。Auto-ts-inline-types简介为了克服TS变量类型声明过于繁琐的缺点,节省开发成本,推荐使用VSCode插件【Auto-ts-inline-types】。它可以通过可视化窗口模拟一个网络请求。通过接口返回的信息或手工修改的信息自动生成相应的TS语句。本文主要介绍插件中Json对象生成TS语句的转换原理。转换原理(1)生成所有接口对象首先遍历需要转换的Json对象,遍历该对象的所有属性。当属性key/value中的值为对象时,开始递归循环。当遍历一个对象,发现所有属性的值都是基本类型时,生成typeDescription(包括HashId和typeObj)。(备注:HashId是引入第三方包Hash后将typeObj转化为HashId得到的,通过HashId保证typeDescription的唯一性)//数据结构示例:constHashId='cc1c310866bbc757b533d7650c9e9934b2e47bf9';consttypeObj={名称:字符串;版本:字符串;描述:字符串;主要:字符串;作者:字符串;license:string;}从内层开始递归到外层依次返回,最后返回的typeStructure包含rootTypeId和types(包括所有生成的typeDescriptions)。(注意:如下图所示,所有的接口声明都包含在生成的types数组中。types中每个元素的HashId属性用于维护元数据Json对象的层级关系。但在类型中,所有对象都是平等的,因为生成的接口都是平等的。在后续的转换过程中,HashId会被替换成变量名生成TS语句)如果发现某个对象的属性中有一些值是数组类型,就会递归遍历数组。Value为数组的情况有五种:数组的typeDescription结构如下图所示。[arrayOfTypes]表示数组中的所有元素类型;[isUnion]代表上表中元素类型(多元素类型)的第五种情况。(2)生成对应的Names数组,将接口返回的信息转化为rootTypeId和types组成的对象后,需要通过HashId和types的对应关系,找到HashId对应的Key,然后改变第一个Name中Key的字母大写生成接口。维护一个HashId和Name的Json对应关系后,存入Names数组,在转换过程结束时替换。首先判断Json对象转换出来的TypeStructure对象的结构,取出RootTypeId。在types数组中找到RootTypeId对应的typeDescription,遍历typeObj。根据typeObj的数据结构,通过arrayOfTypes判断是否为数组。如果是数组,则生成对应的类型。如果是对象,则自动生成对象(包括HashId和name)放入names数组中。(3)根据HashId映射生成TS语句。通过HashId进行映射,将Names数组中的名字作为接口的名字。在types数组中,根据HashId查找各个接口的属性。如果现有属性的值为HashId,则在Names中查找对应的名称。将生成的接口对象转化为字符串,包括接口和JSDoc注释。/***@description构造接口结构*/functiongetInterfaceStringFromDescription(_a){varname=_a.name,typeMap=_a.typeMap;//构造接口内部结构varstringTypeMap=Object.entries(typeMap).map(function(_a){varkey=_a[0],name=_a[1];return""+key+":"+name+";n";}).reduce(function(a,b){return(a+=b);},"");//注解描述vardescriptionName=`/**n*@description${name}n`//属性类型vardescriptionTypeMap=Object.entries(typeMap).map(function(_a){varkey=_a[0],name=_a[1];return"*@param{"+name+"}"+key+"n";}).reduce(function(a,b){return(a+=b);},"");//文档注释vardescriptionString=descriptionName+descriptionTypeMap+\'*/n\'//构造接口结构varinterfaceString="interface"+name+"{n";interfaceString+=stringTypeMap;interfaceString+="}";returndescriptionString+interfaceString;}(4)生成JSDoc注释可以在接口返回信息中直接通过注释添加各个字段的含义手动收集所有注释信息用户添加生成评论信息的json结构,在接口的返回信息中,去掉用户的评论,这样返回的文本信息可以转换为Json结构,在转换后的结果中,替换掉已经评论的意思字段,并写入生成的JSDoc注释中。/***将中文意思写入JSDoc注释中*/constgetFinalInterface=(text:string)=>{for(letkeyincommentJson){//commentJson之间的对应关系字段及中文含义text=text.replace(key+\'n\',key+\'\'+commentJson[key]+\'n\');text=text.replace(key+"\'"+\'n\',key+"\'"+\'\'+commentJson[key]+\'n\');}返回文本;};问题总结自动生成接口对象的顺序是递归的json对象最外层接口(RootType)的顺序会写在生成文件的最下面。目前是手动调整顺序,名为RootType接口的声明放在最前面,其余字段按照从上到下的顺序排列。if(name===\'RootObject\'){//如果是根对象,将其添加到数组的头部nameMap.unshift({id,name});}else{//如果是另一个对象,添加到数组中然后添加nameMap.push({id,name});}如果接口返回的信息中有多个相同键名的字段,用户手动写不同的意思。目前,JSDoc注释以相同的含义注释所有键名。