当前位置: 首页 > Web前端 > vue.js

TypeScript笔记总结

时间:2023-03-31 20:32:40 vue.js

typescript总结笔记前言介绍了typescript的优点静态弱类型语言,编译时会报错,减少出现bug和低级错误的可能性自带代码提示,类型注解对multi更友好-人合作项目,降低沟通成本为什么要学习ts除了上面的一些优势,ts可以帮助我们锻炼数据类型思维(数据定义:datatype&structure),提高我们编码的严谨性和代码的健壮性;本篇笔记是根据ts的理论基础和实践得出的一些结论。我们在写ts项目的时候,往往会对对外输出的变量类型进行限制,而对于从外部输入到项目中的数据结构和类型,比如接口,我们往往没有办法进行限制。虽然也可以限制返回的数据,但是感觉有点鸡肋。另外:泛型的使用很灵活。。。多写点,了解一下理论基础。常用类型的基础知识很快就会过一遍...stringlets:string='iamstring'numberletn:number=1booleanletb:boolean=truenull&undefined//undefined类型的变量只能赋值为undefined//null类型的变量只能赋值为null//其他类型的赋值会报错letud:undefined=undefinedletnu:null=nullvoidvoidvalue//没有返回值的函数是void//声明一个voidtype只能赋值为undefined和nullconstpopup=():void=>{console.log('functionnoreturn')}letuseless:void=undefinedany任何类型,实在没办法就用这个//被任何值赋值,将未指定类型的变量声明为anyletanyType:any='str'unkonwnletuk:unknown;//unknown和any之间的主要区别是未知类型更严格:在对未知类型的值执行大多数操作之前,我们必须执行某种形式的检查,这通常可以通过作为断言,而我们不必在对任何类型的值执行操作之前进行任何检查//当确定未知类型为某种类型时,不能再进行任何操作,比如实例化数组arrayletarr1:(number|string)[]=[1,2,3,'2121']letarr2:数组<数字|boolean>=[2,2,2,true]tuple//表示已知元素个数和类型的数组,每个元素的类型不必相同;越界不能访问//在函数的剩余参数中定义参数lett1的个数和类型:[string,number,boolean|string]t1=['hello',123,false]never//永远不存在的值类型//nevertype:alwaysthrowsanexceptionorThereturnvaluetypeofafunctionexpressionorarrowfunctionexpressionthatwillnothave一个返回值//不能赋值给never类型以外的其他类型,也不能接受其他类型consterr=(msg:string):never=>{thrownewError(msg)}//err('hahaahah')symbolletss:symbol=Symbol('hello')console.log(ss)object表示数据类型为objectletobj:{name:string,value:number}={name:'huhua',value:1232}letobj1:object={name:'haha',value:1232}console.log(obj,obj1,obj.name)//console.log(obj1.name)//名字不在对象的函数上。letmyAdd=(x:number,y:number):number=>x+yletadd=(x:number,y:number)=>x+y//类型推断,不需要指明返回值输入console.log(myAdd(1,2),add(3,100))计算:(x:number,y:number)=>number//定义函数类型compute=(aaa,bbb)=>aaa+bbbenumerationtypeenum枚举:我们可以理解为一组常量,可以帮助我们解决一些硬编码的问题尤其是if语句中的判断值。数值枚举exportenumEState{one=1,two,three,four,five,six,seven}可以取正负值:EState['one']===1;EState[1]==='one'方便维护一个状态数组;另外,在组件中,可以赋值给一个变量字符串枚举enumDirection{Up='Up',Down='Down',Left='Left',Right='Right'}console.log(Direction['右'],Direction.Up);//RightUp异构枚举(混合)enumStrNum{n=0,y='yes'}常量枚举(const声明)//当只需要对象的值来提高性能时可以使用const枚举constenumDirection{Up='Up',Down='Down',Left='Left',Right='Right'}constup=Direction.Upconsole.log(up)接口接口(Interfaces)用于描述“形状”对象(形状)”。接口通常用来约束我们定义的对象、函数、类的结构和类型。对象约束//赋值,变量的形状必须和接口的形状一致(不能多也不能少,而且类型必须一致)interfacePerson{readonlyid:number//只读属性名:stringage:numbersex?:string//可用的选中属性[key:string]:any//索引类型,值为任意属性;theabovemustbeachildofany}函数约束只是对函数形状的约束,没有实质性的声明和计算接口Func{(x:number,y:number):number}letaddSum1:FuncaddSum1=(a,b)=>a+bclassconstraints//不同类之间的公共属性或方法可以抽象成一个接口,由类实现(implements)//该类必须实现接口中声明的所有属性;可以定义接口未声明的属性//接口只能约束类public的公共成员//接口不能约束类接口的构造函数man{name:stringage:number}classHuhuaimplementsMan{//类中声明的公共属性name!:string//赋值断言age!:numberconstructor(name:string,age:number){this.name=namethis.age=age}eat(){console.log('eatfood')}}interfaceinheritance//接口继承interfaceinterfaceAlarm{alert();}interfaceLightableAlarmextendsAlarm{lightOn();lightOff();}//接口继承类classPoint{x:number;y:number;}interfacePoint3dextendsPoint{z:number;}letpoint3d:Point3d={x:1,y:2,z:3};functiontypefunctiontypedefinition://functiondeclarationfunctionadd(a:number,b:number){returna+b}//类型结构声明,表达式附加声明letadd:(a:number,b:number)=>numbertypeAdd:(a:number,b:number)=>numberinterfaceIAdd{(a:number,b:number):number}parameters//可选参数,默认参数,剩余参数:注意顺序functionadd(a:number,b=100,c?:number){returnc?a+b+c:a+b}functionadd(x:number,...rest:number[]){returnx+rest.reduce((pre,acc)=>pre+acc)}函数重载函数with同名兼容多种类型,根据不同的参数实现不同的功能,进行匹配函数add(...rest:number[]):numberfunctionadd(...rest:string[]):stringfunctionadd(...rest:any[]):any{letfirst=rest[0]if(typeoffirst==='string'){returnrest.join('')}if(typeoffirst==='number'){returnrest.reduce((pre,acc)=>pre+acc)}}类的类型classts主要是添加类型注解和成员修饰符;ES6中类的数据类型是函数,类本身指向构造函数,其方法定义在构造函数的prototype属性上。我们可以通过ClassName.prototype.xxx来访问类声明classCar{//实例属性:这个声明必须有一个初始值_wheel:number=4//实例属性成员构造函数:通过返回实例对象(也就是this)defaultconstructor(name:string){this.name=name}//只读属性readonlyoil:string='gasoline'//publicdefault:成员可以被外部访问publicname:string='car'//实例方法run(){console.log(this.name+'runing...')}//私有成员:成员只能从类内部访问privatepriv(){console.log('priv')}//受保护的成员:成员只能被类内部和类的子类访问protectedpro(){}//静态成员:可以被类名及其子类名调用staticseats:string='seat'}letbz=newCar('benz')//通过new实例化letbm:Car=newCar('bm')//classtypeconsole.log(Car.seats)classinheritsclassBmwextendsCar{constructor(name:stirng,publiccolor:string){//先调用父类的实例super(name)this.color=color}}console.log(Bmw.seats)abstractclass抽象类一般不能实例化作为基类,我们可以提取其他类的公共属性和方法写入抽象类abstractclassAnimal{//abstract关键字用于定义一个抽象类,在抽象类abstract中定义一个抽象方法说():无效;move():void{console.log('icanmove')}}classDogextendsAnimal{//在抽象类中声明方法,子类可以重写父类方法;实现所谓的多态say(){console.log('Wowwoof');}}letdog1=newDog()dog1.say()//woofwoofdog1.move()//我可以移动类实现接口不同的类它们之间可以有一些共同的特征。这时候就可以把特性提取到接口(interfaces)中,用implements关键字实现。//类必须实现接口声明的所有属性(相当于约束公共属性);接口可以定义未声明的属性//接口只能约束类的公共成员public//接口不能约束类构造器interfaceAlarm{alert();}interfaceLight{lightOn();lightOff();}类Car实现Alarm,Light{alert(){console.log('Caralert');}lightOn(){console.log('车灯亮');}lightOff(){console.log('车灯关闭');}}泛型(相当于给类型传递参数)泛型:在定义函数、接口或类时,事先不指定具体类型,而是在使用时指定类型的特性,同时指定类型声明变量的类型值//1.函数约束//类型T不需要预先指定就等同于any类型//保证输入类型和返回值类型一致才能使弥补任何类型函数的缺点log(v:T):T{returnv;}lets:string="generics";leta=log(s);console.log(a);console.log(log(1111));//2.函数类型约束//联合类型、类型别名和字符串字面量类型都是用type定义的。//类型Log=(v:T)=>T//类型别名接口Log{(v:T):T;}letmyLog:Log=log;console.log(myLog([1,2,3]));//3.泛型接口//接口的所有属性都可以被泛型变量约束//可以传入默认类型interfaceIGeneric{(v:T):T;}letIG1:IGeneric=log;console.log(IG1(123));//4.泛型类classGenericNumber{//泛型变量不能约束类的静态属性//zeroValue:T=T;添加(x:T,y?:T){console.log(x);返回x;}}letmyGenericNumber=newGenericNumber();myGenericNumber.add(1);letmyG1=newGenericNumber();myG1.add("hellotsgenerics");//5.通用约束接口Length{length:number;}//T继承了Length接口,所以入参必须有length属性才能取值。length是合法函数ggg(value:T):T{console.log(value,value.length);returnvalue;}ggg('hello')ggg([1,2,3])进阶理论ts类型检查机制根据tsconfig.json的配置规则进行类型推断,上下文推断,类型断言as,双重断言,is关键字:xxisstring,赋值断言letx!:string类型兼容不同变量相互赋值时类型检查函数兼容性:参数个数,参数类型,返回值类型接口兼容性:一个类型可以赋值的成员更少with更多成员需要保护在特殊块中使用确定类型的属性和方法,比如使用联合类型变量的方法1.instanceofif(cinstanceofA)c.a2.inif(cinC)c.a3.typeof函数的参数为??联合类型if(typeofarg==='string'){}else{}4.声明类型保护方法文字联合、交叉、索引类型交叉和合并类型属性联合|指定类型的所有可能索引//缩小类型的约束范围;//索引类型查询操作符KkeyofT:联合类型的集合;//索引类型访问运算符T[K];//泛型约束TextendsUinterfaceIObj{a:stringb:number}letkey:keyofIObjletk:IObj['a']letiobj={a:1,b:2,c:'ccc'}//泛型索引约束函数getObjValue(obj:T,keys:K[]):T[K][]{returnkeys.map(key=>obj[key])}console.log(getObjValue(iobj,['a','c']));//console.log(getObjValue(iobj,['a','d']));防错工程实践篇下面是我们在正式开发中使用ts的一些技巧和规范tsconfig.json//ts项目配置文件说明https://segmentfault.com/a/11...http://www.typescriptlang.org...declarationfilexxx.d.tsdeclarevardeclaresglobalvariabledeclarefunctiondeclaresglobalmethoddeclareclassdeclareglobalclassdeclareenumdeclareglobalenumeration取类型declarenamespace声明全局对象(带子属性)declaretheglobaltypeexportexportvariableexportnamespaceexporttheobject(withsub-attributes)exportdefaultES6默认导出=commonjsexportmodule,importxx=require('xxx')exportasnamespaceUMD库声明全局变量declareglobal扩展全局变量declaremoduleextendsmoduletstoolclass(generic)Partial:makeallattributesoptional.typePartial={[PinkeyofT]?:T[P]};typep=PartialRequired:ChangeoptionaltomandatoryExclude:从T中排除可以分配给U类型的元素T=Exclude<1|2,1|3>//->2Omit:Omit的作用是忽略T中的某些属性。typeFoo=Omit<{name:string,age:number},'name'>//->{age:number}Merge:Merge的作用是合并两个对象的属性:Intersection的作用是取T的属性,这个属性也存在U.OverwriteU的属性覆盖了T中相同的属性。开发的一些技巧待更新。。。vue项目中使用的一些问题我第一次在vue项目中使用,发现支持不是很好...不过还是咬牙写完一个项目,打算在react中使用相关插件文档vue-class-component:https://github.com/vuejs/vue-docs-zh-cn/tree/master/vue-class-componentvue-property-decorator:https://github.com/kaorun343/vue-property-decoratorvuex-class:https://github.com/ktsn/vuex-classvuex-module-decoratorshttps://github.com/championswimmer/vuex-module-decorators类型断言:types用于绕过ts编译器查看;即手动指定值的类型value=>valuevalueastype=>valueasstring(this.$refs['multiTable']asany).clearSelection()(this.$refs['downParams']asForm).resetFields()$refsDoubleassertion((this.$refs.saveTagInputasVue)['$refs'].inputasHTMLInputElement).focus()使用三者时安装或编写自己的语句-partylibrary文件@types/xxx待续,稍后更新...