TypeScript一直被称是javascript的未来最终形态,工作原因一直未接触到这块,有些疑问一直未解决:TypeScript到底好在哪里?经常说的强类型语言更适合开发大型应用,又为什么更适合?抽点时间,咱一起来看看吧。
javascript我们都知道它对于变量其实并没有做过多的约束,一个var能走遍天下,String是var,Array也是var,Object也是var,另外:
咋一看好像没问题,也是OK的。即使是ES6的let,const也一样,虽说这两个在作用域的处理以及读写权限的优化上好了很多,但在类型这块,也是可以这样的:
我们可以随意转化数据类型,非常方便,对吧?
但在很多后端或者系统方面的人来说,这其实很可怕。就跟我们不知道啥时候就冲突或变量覆盖了一样,变量可能某个逻辑完成后连类型都不一样了。。。
在Ts中,可能抛出这样的错误:直接跟你说hello world不能赋值到一个数组类型的变量上。
js在设计之初是用于前端,表单验证等,传统的前端对于数据的处理其实很有限,更多的是在于DOM的处理,即使是MVVM框架对于数据的处理,也只是停留在JSON数据的处理上。用js做计算也有很多问题,比如:"112" < "29",这很奇怪,但能比较。另外,Number类型的数据可以跟String类型的比较。
无论是变量类型,还是模块,作用域等等的限制,强类型语言总被说更适合开发大型应用是有原因的,因为大型应用是复杂的,种种规则的约束下代码才更容易按照当初设想的方式来工作,应用的问题更易于定位。大型应用需要的团队协同开发,长时间的迭代也更需要一门约束性较高,延续性较好的语言。开发人员代码写出的Bug,编译能抛出不留到运行才抛出,而这些都是js这门自由的语言最最缺乏的。
后端很考验性能,由于每一种数据类型在实际的计算机存储中的存储方式是不同的,类型间的频繁强转换在很多时候是很浪费资源且没必要的,所以后端语言更强调的是从一而终,即声明了某个变量的数据类型,这个变量在内存中的存储方式就固定了,下次访问就以该存储的方式去访问,无需做类型检查,可以加快速度,提升性能。但这样带来的一个副作用就是我们用着不爽,总得先声明,先定义再使用。但这目前看来是一种妥协。
既然后端对开发语言的需求是这样的,那随着js对前后端的逐步渗透,也对其本身提出了更高的要求,强类型的js也就是TypeScript也就这样出来了。
一起看看Ts与我们熟悉的Js有什么不同,又带来了什么新东西吧。
一、强类型声明方式
Ts为了保持与Js的兼容,与传统的强类型有些不一样的是,不是String a = "dorsey"这样的,而是上图所声明的这样。
那js中用得最多的 —— 函数的声明方式呢?看看哈:
注意到,函数的指针是String类型,必须有一个String类型的返回值。如果没有返回值呢?那就定义成这样(是不是跟C语言特别像?):
你说想用伪类Class写构造函数,没问题啊,主要要注意的就是每个变量都需要声明类型,且不能随意的A类型赋值给B类型。
看看打印了啥?
二、变量类型
相比于Javascript的七大基本类型(ES6新增了Symbol),TypeScript新增了更多种类型,如下:
①:Undefined —— 未定义
②:Number —— 数值类型;
③:String —— 字符串类型;
④:Boolean —— 布尔类型;
⑤:enum —— 枚举类型;
⑥:any —— 任意类型;
⑦:void —— 空类型;
⑧:Array —— 数组类型;
⑨:Tuple —— 元祖类型;
⑩:Null —— 空类型。
类型很多,String,Boolean,Number,Underfined,Null,Array这些常见的就不说了。
先来看枚举:
枚举型在后端有很广泛的应用,它犹如一个字典,存放地址值唯一的常量,什么意思呢?就比如说一年有12个月,有4个季节,地球有7大洲,4大洋,这些不会变吧?起码在我们有生之年暂时不会变对吧?这种字典型的其实js很多时候就有用到,比如写一个车牌code和车牌的字典对象,而这在服务端就可以用枚举来完成。
我们看一下这个枚举,看着很像对象,对吧。
值得注意的是,enum枚举类型本身就是用于定义常量的,所以你不可以这样操作:
编译器会报错,提示你不能这样来改变。
再来看看any:
TypeScript毕竟还是Javascript进化而来,潜意识中更加注重实用者的体验,可能有些人一直用var,let用得很爽,突然每种变量都要声明且不做强制类型转换的话只能用一种类型,会有种急刹车,转不过弯的感觉,而这时候你就可以用any。比如说这样:
这样就不会报错,也可以随意转换类型。
但是TypeScript的使用场景注定了不这样去做变量类型随意改变,最好少用或不用。
再来看看Tuple:
后端的开发有一个非常非常广泛的类型,很像数组,那就是list(list<Object>),它是一个有序集合。而在TypeScript没有list,它有另一个叫法,叫Tuple元祖。
什么是Tuple,list?有什么用,既然跟数组很像为什么不用数组?我们看一个在前端我们都觉得没啥的东西。
这乍一看好像没什么问题,对吧?但是假如说你是强类型语言呢?你得定义各个索引上的值类型对吧?要么不定义就统一成某种特定类型的数据类型,对吧?
在后端,数组内部的类型是不允许这样的,你的这样定义:
number用于规定数组内部的数据是某种特定类型的数据。这很多时候很不友好,因为数组内部的成员可能有很多种类型,而即使是java,C++等强类型语言一个个去定义显然也是不现实的,这样就诞生了list这样的东西。正因为前端代码撸多了,对于类型的弱化,遇上这样的情况会很不适应。而typeScript可能是想跟其他后端语言区分开或者什么缘故,定义成了元祖类型,这我们不管。
那Tuple类型的数据又是怎样的呢?
哈哈,你没看错,就是跟普通的javascript定义的类似,只不过会被定义为tuple类型。
emmmm,好像还有一个void类型?这个就是我们刚接触C语言时最常用的
void add(int a, int b){printf("%d", a + b)}对吧。一样的。只需要知道大多数时候用于一个无返回值的一段逻辑。
Typescript的联合类型:
正因为javascript的变量自由,Typescript提供了一个很独特的类型方式,允许你在某几种类型中自由变换。当然,有一定的实际应用场景,且相应的风险起码是可控的。比如你可以这样:
或者这样:
但你仍然不可以这样,因为这样是元祖tuple类型而非数组类型。
当然函数的参数,也是运行联合类型的。
Typescript接口:
既然是用来做后端语言的,那就不得不提接口二字,那Typescript的接口又是怎样的呢?一起看看吧。
看看打印的结果呢?
那接口的输入输入呢?
这个跟ES6的很像,只不过Typescript可以导出接口而已。
暂时先这么多吧。