TypeScript可以看成是JavaScript的超集,它不仅包含了JavaScript的所有内容,还扩展了语法,指定了类型约束,让我们可以写得更干净,完全代码。TypeAnnotationsTypeScript提供了很多数据类型,通过类型来限制变量,称为类型注解。使用类型注解后,变量的类型不能随意改变。下面的代码定义了一个字符串类型的变量。如果改成数字类型,在代码编译阶段会直接报错,提示“Type'number'isnotassignabletotype'string'”。这样就保证了变量的数据类型是固定的,那么它可以使用的方法也就确定了。不会出现变量本来是字符串,调用了toUpperCase方法,后来在未经测试的场景不小心改成了数字。type之后调用toUpperCase直接报错。类型推导当变量没有写数据类型时,ts会在内部进行“类型推导”,通过上下文赋值语句判断变量的数据类型,所以当类型注解比较简单时,可以准确自动推导类型,不写类型注解对代码质量也没有影响。TS和JSTypeScript共享的数据类型包括JavaScript拥有的数据类型,如string、number、symbol、array、boolean、undefined、null和object。其中,在定义数组时,需要加上数组中每条数据的类型,是字符串、数字还是对象,这样就无法在数组中写入多种数据类型。如果需要写多种数据类型,可以直接不加类型注解,【类型推导】会自动进行。letstr:string="string";letnum:number=0;letsym:symbol=Symbol("sym");letarr1:string[]=['alice','kiki','heidi']让arr2:object[]=[{name:'alice'}]让arr3:number[]=[1,2,3]让flag:boolean=false;让und:undefined=undefined;让nu:null=null;letuser={name:"alice"};上面的对象user也是没有类型注解的,因为如果定义为对象类型,则无法获取和修改user对象上的属性。这是因为user是object类型,但是object类型上没有name属性,所以在编译阶段会直接报错,所以不能给object加上类型注解,让它自动进行类型推导.TS独有的数据类型此外,TypeScript还加入了很多JavaScript没有的数据类型。anyany是一种“灵丹妙药”数据类型,意思是“任何”数据类型。当变量的类型不确定,可能发生变化时,可以定义为any,此时变量的数据类型可以随意改变,这实际上带来了一些安全隐患。例如,下面的代码使用字符串作为函数,undefined使用数字。因为是任意类型,类型可能会变成字符串,数字,或者布尔值,所以这样的代码是不会被ts检测到的,但是运行时肯定会报错。letmessage:any="message";message();message=0;message=undefined;message.toFixed();unknown当变量的类型暂时不确定时,可以使用unknown来限制其类型。letflag=trueletresult:unknown;if(flag){result='HelloWorld'}else{result=888}和any有点类似,不同的是unknown不能赋值给any和unknown类型以外的变量,这样就不能在其他地方使用unknown的值。void当函数没有返回值时,实际上返回的是undefined。void通常用于表示函数返回值未定义或为null。以下形式都是可能的functionadd():void{}functionsub():void{returnundefined}functionmul():void{returnnull}当有返回值时,编译会报错。nevernever表示永远不会存在的类型,如果函数是无限循环或抛出异常,则可以使用。functionfoo():never{while(true){}}functioncatchError():never{thrownewError("error");}我们在封装工具函数的时候,函数的初始入参是string类型,但是可能后来在别人的开发过程中,增加了number类型。为了避免在维护时忘记处理这类数据,可以将入参赋值给一个never类型的变量,这样编译就不会通过,防止开发者忽略逻辑。tupletuple是元组的意思,类似于数组,但是元组和数组还是有以下区别的。数组中元素的数据类型建议保持一致。当数据类型不一致时,考虑将它们放在元组或对象中。元组中的每个元素都有自己的特征,可以通过索引值获取。//Arrayconstarray:string[]=["alice","kiki"];//Tupleconsttuple:[string,number]=["alice",20];声明函数参数和返回值时,在函数的每个参数后加上类型注解,声明函数接受的参数类型,限制参数类型和参数个数。函数列表后面定义的类型注解,用于限定函数的返回值类型。//限制输入类型functionfoo(message:string,no:number){}//限制返回值functionbaz(message:string):string{return"string";}输入参数type/number不对时符合标注要求,编译时会标注红色以示提醒。对象类型、可选类型和联合类型也可用于指定函数输入参数。对象类型,定义了对象中各个参数的数据类型Optional类型,带?表示该参数是可选的,必须写在需要的类型之后。关节类型用|、A|表示。B表示输入参数类型为A和B中的任意一种。getPoint({x:10,y:20,z:30});functionprintId(id:string|number){}printId(1);printId("alice");functionfoo(message?:string){}foo("message");foo();当指定的类型比较长时,可以通过type键Word来定义类型别名,参数类型为[optionaltype]可以理解为参数类型和undefined[uniontype],下面的入参两个参数本质上是一样的类型断言有时TypeScript获取的类型比较广泛。这时候就可以使用类型断言,通过关键字as来定义具体的数据类型。例如,下面定义了两个类。Student继承自Person类,有自己的学习方法。定义了sayHello方法,要求入参类型为Person。此时创建了Student实例对象student,调用sayHello方法传入student。classPerson{}classStudentextendsPerson{studying(){}}functionsayHello(p:Person){}conststudent=newStudent()sayHello(student)上面的代码编译时没有问题,但是如果sayHello呢不允许在方法中调用Student实例对象的study,因为传入的参数虽然是Student实例对象,但在TypeScript中只能检测为Person类型,Person上没有study方法。要正确调用它,需要使用类型断言来指定输入参数函数的实际类型sayHello(p:Person){(pasStudent).studying()}非空类型断言通过!防止无法编译的代码被标红的符号,但是如果代码在运行时出现问题,还是会抛出错误。字面量通过const定义的变量的数据类型就是字面量类型,字面量中的值就是赋给变量的内容。字面量类型可以用来指定变量的选择范围。比如flex布局的方向可以选择row或者columstypeDirectionType="row"|“列”;让方向:方向类型=“行”;方向=“列”;当变量被赋值时,其类型注解中没有包含的值,会被标记为红色,以示提醒。类型缩小类型缩小是指当变量数据类型的范围比较大时,我们可以使用if、switch、in、typeof、instanceof等来判断和缩小变量的类型,以实现更精确的操作。比如函数的参数类型可能是string和number,直接获取length属性会报错。因为只有string类型的变量可以获得length,而number类型的变量是不存在的,所以这时候可以使用typeof来判断输入参数的类型。该确定步骤也称为“类型保护”。ts中的这些类型注解可以帮助开发者在开发的时候更好的规范代码,减少上线失败~以上就是关于TypeScript类型注解的内容。关于js和ts,开发者需要掌握的东西还是很多的。大家可以看看我写的其他博文,正在更新中~
