当前位置: 首页 > 科技观察

你仍然只在TypeScript中使用Any吗?

时间:2023-03-13 22:33:20 科技观察

刚开始学习TypeScript的时候,是不是遇到了很多让人抓狂的问题,最后用什么大招解决了问题。如果后面你不系统地学习TypeScript的类型系统,你会发现你可能把TypeScript学成了AnyScript。在TypeScript中,any类型被称为顶级类型。所谓顶级类型可以理解为一个通用的父类型,即可以包含所有值的类型。让值:任何;值=真;//确定值=42;//OKvalue="HelloWorld";//确定值=[];//确定值={};//OKvalue=Math.random;//确定值=null;//OKvalue=undefined;//OKvalue=newTypeError();//OKvalue=Symbol("type");//OK在TypeScript3.0中,引入了一个新的顶级类型——未知类型。同样,您可以将任何值分配给未知类型的变量。让值:未知;值=真;//确定值=42;//OKvalue="HelloWorld";//确定值=[];//确定值={};//OKvalue=Math.random;//确定值=null;//OKvalue=undefined;//OKvalue=newTypeError();//OKvalue=Symbol("type");//OK那么现在问题来了,any类型和unknown类型有什么区别?any类型可以理解为不关心它的类型,unknown类型可以理解为不知道它的类型。事实上,any类型本质上是类型系统的逃生通道,TypeScript允许我们对any类型的值执行任何操作,而无需事先进行任何类型的检查。让值:任何;value.foo.bar;//OKvalue.trim();//确定值();//确定新值();//确定值[0][1];//OK这会带来什么问题呢?让我们举个例子:functioninvokeCallback(callback:any){try{callback();}catch(err){console.error(err)}}invokeCallback(1);对于上面的TS代码,在编译时不会出错,但是在运行时会抛出运行时错误。作为开发者,any类型给了我们很大的自由度,但也带来了一些隐患。为了解决any类型的安全隐患,TypeScript团队在3.0版本引入了未知类型,可以理解为类型安全的any类型。那么未知类型从哪里体现类型安全呢?这里我们将invokeCallback函数参数的类型改为未知类型,TS编译器会提示相应的错误信息:functioninvokeCallback(callback:unknown){try{//Objectisoftype'unknown'.(2571)打回来();//错误}catch(err){console.error(err)}}invokeCallback(1);与任何类型相比,TypeScript都会执行typeunknowntypevariableCheck以避免非函数类型的回调参数。要解决上面的问题,我们需要缩小回调参数的类型,即我们可以使用typeof操作符保证传入的回调参数是一个函数类型的对象:functioninvokeCallback(callback:unknown){try{if(typeofcallback==='function'){callback();}}catch(err){console.error(err)}}invokeCallback(1);在实际工作中,还可以使用instanceof或者用户自定义的类型保护来缩小变量类型。declarefunctionisFunction(x:unknown):xisFunction;functionf20(x:unknown){if(xinstanceofError){x;//错误}if(isFunction(x)){x;//Function}}和any类型不同,因为TypeScript会对未知类型的变量进行类型检查,所以当我们把前面代码中的value变量的类型改成未知类型时,多个语句使用value变量会有错误。letvalue:unknown;//对象的类型为“unknown”。(2571)value.foo.bar;//错误值.trim();//错误值();//错误新值();//错误值[0][1];//Error另外需要注意的是,未知类型的变量只能赋值给任意类型和未知类型本身。设值:未知;设值1:未知=值;//OKletvalue2:any=value;//OKletvalue3:boolean=value;//Errorletvalue4:number=value;//Errorletvalue5:string=value;//Errorletvalue6:object=value;//Errorletvalue7:any[]=value;//Errorletvalue8:Function=value;//Errorlet类型和未知类型在这些情况下表现不同:typeT40=keyofany;//字符串|编号|symboltypeT41=keyof未知;//nevertypeT50={[PinkeyofT]:number};typeT51=T50;//{[x:string]:number}typeT52=T50;//{}在上面的代码中,T50类型称为映射类型。在映射过程中,如果key的类型不是never类型,则当前key会被过滤掉,所以T52的type是空对象类型。这里介绍any类型和unknown类型的区别。现在总结一下:可以给任意类型的变量赋任意值,对变量进行任意操作;您可以将任何值分配给未知类型。变量,但必须进行类型检查或类型断言才能对变量进行操作;在平时的工作中,为了保证类型安全,我们应该尽可能的使用未知类型。最后,让我们看看未知类型和不同类型之间的类型操作结果://InanintersectioneverythingabsorbingunknowntypeT00=unknown&null;//nulltypeT01=unknown&undefined;//undefinedtypeT02=unknown&null&undefined;//null&undefined(在联合中永远不会)typeT03=unknown&string;//字符串类型T04=unknown&string[];//字符串[]类型T05=未知&未知;//未知类型T06=未知&任何;//any//在联合中,一个未知吸收所有类型T10=unknown|无效的;//未知类型T11=未知|不明确的;//未知类型T12=未知|空|不明确的;//未知类型T13=未知|细绳;//未知类型T14=未知|细绳[];//未知类型T15=未知|未知;//未知类型T16=未知|任何;//anyany类型比较特殊,当此类型与任何类型交叉或组合时,将返回任何类型。看完这篇文章,相信你已经明白anytype和unknowntype的区别了。你知道如何检测任何类型和未知类型吗?