vue中tsconfig的使用场景注意事项注意需要引入strict:true(或者至少是noImplicitThis:true,属于strict模式的一部分)来利用类型this在组件方法中检查,否则它将始终被视为任何类型。需要注意以下配置项,否则类型推断将无法正常工作//启用所有严格类型检查选项"strict":true,//禁止这个值来自任何"noImplicitThis":true,Vue的作用.extend()vue.extend方法已经声明了参数类型,所以vue.extend可以为你提供类型推断。例如,看下面这段代码:typevueExtend=(option:{name:string,$store:object,$route:object})=>void;constvueInstance:vueExtend=({$}){};vueprototype在属性或方法中混入我们平时写的$store或$route等方法插件,将prototype属性$store和$route添加到Vue原型中。那么如何在ts中的vue原型中混合这些属性或者方法呢?从vuex导出的ts声明文件中,我们可以看到如下代码:{store?:Store;}}declaremodule"vue/types/vue"{interfaceVue{$store:Store;所以如果我们想混入$api,我们需要做同样的事情。首先新建一个global.d.ts,使用如下代码};}//使用this.$api.queryHotel(payload).then(()=>{});推断vue组件实例类型。为什么需要推断vue实例类型?这是一个使用场景。比如当我们需要获取子组件的引用,调用子组件的方法时。假设此时子组件为SpaceDrawer,ref为spaceDrawer。//同步移除IoT树的节点(this.$refs.spaceDrawerasany).removeCheckNode(delRoomNode[0]);获取SpaceDrawer实例类型typeSpaceDrawerRef=InstanceType;//同步移除IoT树节点(this.$refs.spaceDrawerasSpaceDrawerRef).removeCheckNode(delRoomNode[0]);Vue组件实例SpaceDrawer可以通过高级类型InstanceType获取。在vue中重新声明data中属性的类型vue中的类型得益于vue.extend可以自动推断类型,但有时你需要自定义类型。下面的例子exportdefaultVue.extend({data(){return{obj:{name:'',value:''}}},methods:{handleObj(type:string){//这是可能的this.obj.name='xxx';//这样是不行的,(比如type是name)this.obj[type]='xxx'}}})如上面两种情况,显然第二种类型需要重新定义类型,因为this需要使用可索引类型。我们可以重新定义data中字段的类型,即类型断言。如下:typeObjType={[key:string]:string;名称:字符串;value:string}exportdefaultVue.extend({data(){return{obj:{name:'',value:''}asObjType,}},methods:{handleObj(type:string){//这是possiblethis.obj[type]='xxx'}}})vue中重新声明的props的类型和data类似,只是vue的类型系统已经给我们提供了断言的类型——PropType用法如下:export默认Vue.extend({props:{spaceModel:{type:NumberasPropType,default:SpaceModelEnum.All,},spaceOperator:{type:StringasPropType,default:SpaceOperator.CREATE,}},getincomputed,set使得类型推断异常,这里需要注意,有时候类型推断不起作用,computed出现异常,这是因为computed异常阻塞了类型的进一步推断,在以下情况下,此时无法推断出prop中的属性:解决办法是完成本写的类型声明让mixins得到类型推断Letmixinsgettypeinferencemixins属性按照惯例写在组件中,无法推断出mixins中的组件类型。例如,这是一个mixins组件接下来在组件中引用它。从'vue'导入Vue;从'./mixinTest.vue'导入MixinTets;导出默认Vue.extend({name:'TagList',components:{},props:{tagList:{type:Array,required:true,},},mixins:\[MixinTets\],data(){return{};},方法:{handleClickTag(item:any){this.tthis.$emit('handleClickTag',item);},},})我们发现无法正确导出组件的实例(这里应该有test和ok方法)。那么我们如何解决这样的问题呢?首先,我们需要提供类型推断。这里看不懂也没关系,只是对vue实例中的mixins方法做一个类型推断。推断传入单个vue实例,传入多个vue实例,完成类型交叉。/\*eslint-disablemax-len,import/export,no-use-before-define\*/importVue,{VueConstructor}from'vue';exportdefaultfunctionmixins(...args:T):ExtractVueextendsinferV?(VextendsVue?VueConstructor:never):never;exportdefaultfunctionmixins(...args:VueConstructor\[\]):VueConstructor;exportdefaultfunctionmixins(...args:VueConstructor\[\]):VueConstructor{returnVue.extend({mixins:args});}/\*\*\*从VueConstructor返回实例类型\*在使用mixins()时添加类型很有用。extend()\*/导出类型ExtractVue=Textends(inferU)\[\]?UnionToIntersection?V:从不>:TextendsVueConstructor?V:从不;类型UnionToIntersection=(Uextendsany?(k:U)=>void:never)扩展(k:推断我)=>无效?I:nev根据上面的代码,可以写出如下结构,可以推断出类型({name:'TagList',components:{},props:{tagList:{type:Array,required:true,},},data(){return{};},methods:{handleClickTag(item:any){this.$emit('handleClickTag',item);},},})如何写多个mixin?枚举使代码更清晰。相信大家都知道枚举有两种。一种是常量枚举,一种是普通枚举//1.常量枚举constenumState{SUCCESS=0,FAIL}//2.枚举enumState{SUCCESS=0,FAIL}那么什么时候用常量枚举例如,当使用普通枚举。你只需要知道常量枚举就是js运行时ts的编译值。什么意思?如果将常量枚举视为常量,它将不起作用,因为它不存在。enumSpaceModelEnum{All=0,ONLY_BUILDING_ROOM,ONLY_FLOOR_ROOM,ONLY_ROOM,}constenumSpaceType{BUILDING=0,FLOOR,ROOM,}exportdefaultVue.extend({name:'SpaceCreate',data(){return{//可以使用SpaceModelEnum,//NoSpaceType};},})枚举非常有用,可以大大提高代码的可读性。当然用map也是可以的。switch(level){caseSpaceType.BUILDING:break;案例SpaceType.FLOOR:parentNode=spaceDestruct.genBuildingNode();spaceTree.push(parentNode);休息;案例SpaceType.ROOM:constbuildingNode=spaceDestruct.genAll();buildingNode.children[0];spaceTree.push(buildingNode);default:break;}这里可以清楚的知道level可能是building,floor,roomtype。而不是可读性低的0、1、2码。常用ts高级类型Record-经常使用,方便定义可索引类型,RecordReturnType-获取函数的返回类型ConstructParameter-获取构造函数参数类型typeof-获取对象的类型keyof-获取接口类型的key并组合成一个联合类型in-枚举联合类型一个优秀的ts高级类型开源库:ts-toolbelt一个关于高级类型的博文:【快速参考手册】TypeScriptAdvanced类型备忘单使用泛型来动态推断API接口返回的数据类型。不同的请求接口返回不同的数据类型,那么如何定义这种类型呢?我们很容易想到使用泛型。但是每个接口都会返回一个固定的格式:{code:number;味精:字符串|无效的;result:any;}然后我们需要在第一步中提取通用格式,然后通过泛型动态定义结果。这是我打包的例子。类型ResType={代码:数字;味精:字符串|无效的;结果:T;};api(urlProp:string,params:Record,config={}):Promise>{const{get:urlGet,post:urlPost}=this.url对象;让url=urlGet[urlProp];如果(url&&url.length>0){returnajax.get(url,params,config);}url=urlPost[urlProp];返回ajax.post(url,params,config);}constajax={post(url:string,params:Record,config:AxiosRequestConfig={}):Promise>{returnnewPromise((resolve,reject)=>{axios.post(url,params,config).then((res:AxiosResponse)=>{const{data={}}=res;resolve(data);},(错误)=>{拒绝(错误);});});},};如何使用它?输入HotelSpaceNode={roomId:string;名称:字符串;parentId:string;}api('http://debug.aqara.com/getHotelSpaceNode',{}).then(({code,result})=>{if(code===0){//此时result的类型为HotelSpaceNode[]this.spaceTreeData=result;}});类型断言(强制类型转换)下面是一个例子。比如我定义了一个空的Object,那么我需要给这个对象动态添加属性,但是这个对象依赖于一个接口。怎么做?类型mapNodeType={空间名称:字符串;空间编号:字符串;空间类型:数字;parentId:string;}constmapNode={};const{level,childrenList,roomId,name,parentId,state,spaceState}=currentNode;mapNode.spaceId=roomId;mapNode.spaceName=name;mapNode.spaceType=level;mapNode.parentId=parentId;当然,上面的例子有类型声明更好,不管怎样,它可以提供类型推断和更高的代码可读性。还有一个时候需要分配一个默认值。genFloorNode(spaceNode:FloorSpaceNode={}){consttheSpaceNode=spaceNode;if(_.isEmpty(spaceNode)){theSpaceNode.spaceType=SpaceType.FLOOR;}返回新的FloorSpaceNode(theSpaceNode);}