1
基础动因
对JS执行原理有过了解的同学应该知道,JS代码在执行过程中才会编译,许多文章里引入一个叫做预编译的概念,其实就是我们之前文章说过的执行上下文的创建过程。也就意味着,JS的语法规则检测,是在执行过程中才会进行的一个步骤。
带来的后果就是,在开发过程中的所有语法错误,我们都没办法通过某种方式去完全预知到,而必须在浏览器里执行一次看到报错之后才知道自己某个地方写错了。
当项目稍微复杂一点,无法预知语法错误可以说是一场灾难。一个单词拼错,就足以让你陷入困境。
JS同时也是一门弱类型语言。我们声明一个变量之后,它可以是任意类型,可以在任何时候修改为别的类型。这极大的提高JS代码灵活性的同时,带来的副作用也同样明显,一个变量在我们的应用中无法预知它扮演的角色,维护成本远超想象。
在复杂项目中,我们通常无法承受JS弱类型的副作用,这是typescript出现的基础动因,它让JavaScript具备了强类型语言的特征。当然,除了解决这些基础问题,ts还有许多别的特性。
2
什么是typescirpt「后面简称ts」
官方文档解释说,ts是JavaScript的超集,它可以编译成纯JavaScript。
估计一看这个解释有的同学不太能理解。可以做一个简单的类比,我们在实践开发中,通常使用ES6开发,并且编译成ES5的代码给浏览器执行。所以ES6和ts扮演的角色比较类似。之所以说是JavaScript的超集,就是在JavaScript的语法基础上,新增了更多的语法规则,让JavaScript具备我们期望的特性。所以我们学习ts,其实就是学习这些新的特性,和新特性的应用场景。
总结:ts是一套语法规则,帮助我们约束自己的代码规范。
3
作用1:直接在开发过程中暴露错误
如图所示。
试图修改const声明的常量
试图修改const声明的常量
执行未定义的函数,通常是拼错了已经定义的方法名
与eslint类似,具体的报错语法我们可以通过tslint
来配置规则。
4
作用2:约束变量类型
当我们给变量foo设定为number之后,如果我们试图将其他类型的值赋值给变量foo,那么编辑器就会抛出异常,因为这违反了类型约束的规定。
基础变量约束
5
作用3:描述函数规则,即明确的告诉使用者该函数的参数类型与返回值类型
当我们定义了add函数,要求传入该函数的参数分别为2个number类型,并且返回值也为number类型。那么在使用时,不符合这个规则的用法都会报错。
- error: 传入非number类型的参数
- error: 传入了3个参数
描述函数规则
6
ts作用4:使用interface描述复杂数据
interface IParamA { id: number, name: string } function fetchList(params: IParamA): Promise<void> { return axios.get('/api/demo', params); } fetchList({ id: 1, name: 'alex' });
如上所示的例子,当我们定义fetchList
时,会传入一个JSON对象作为参数,此时我们需要描述该参数的数据类型,借助interface
即可做到,当传入的参数不符合描述的规则时,会抛出对应的错误。
注意关注报错信息
在实践中,数据的复杂程度远不止于此,因此我们还需要借助更多的知识点来描述不同的参数类型,这也是我们学习ts的重点与难点。
例如枚举类型。
/** 枚举 */ enum Direction { up = 1, down, left, right } /** 三种运动方式 */ type MoveType = 'linear' | 'ease' | 'bounce'; function moveToDemo(ease: string, direction: Direction): void { // .. todo console.log(ease, direction); } function moveTo(ease: MoveType, direction: Direction): void { console.log(ease, direction); } moveTo('bounce', Direction.down);
上面这个例子中,我们自定义了一个函数moveTo,该函数接收两个参数
- 运动的动画曲线类型,我们期望在使用该函数时只能传入
linear, ease, bounce
中的一个
- 运动方向, 我们期望只能传入上下左右四个方向值
这里我们借助了type
语法与枚举enum
语法实现了类似的效果。
重点关注coding过程中的代码提示
7
描述class对象。
与ES6语法几乎一样。
class Person { private name: string; private age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } public getName(): string { returnthis.name; } public getAge(): number { returnthis.age; } } const p1 = new Person('alex', 20); p1.getAge(); p1.getName();
注意观察coding过程中的智能提示
8
总结:ts的主要作用在于约束
通过上面的几个简单的例子,我们可以知道,ts的主要作用在于通过各种方式约束我们的代码。也可以这样理解:ts是一套约束规则。而我们只要掌握了这套约束规则,那么带来的另一个好处就是,我们可以更加容易的读懂别人的代码。
除此之外,正因为约束规则的存在,IDE「例如vscode」就可以很容易的做到智能提示,这也是我们要在实践中使用ts的另一个重要原因。
因此,我们学习ts的过程,其实就是学习一套约束规则的过程。
9
快速读懂别人的代码
完善的类型约束与友好的声明文件,能够非常完整的表达一个函数一个组件的作用,因此我们能够非常轻松的读懂别人的代码想要做的事情。更高的可读性,必然也带来的维护成本的降低。bug修改速度加快。
友好的声明文件
10
typescript的重要性
在团队协作中,衡量一个人代码水平最重要的因素是代码可读性。在我看来,它是比性能和技巧更为重要的一个标准。而 typescript 在复杂项目中,对于代码可读性带来的增强是非常具有吸引力的。因此越来越多的团队在项目中深度使用 ts。甚至在 angular 团队中,整个angular
都是直接使用ts开发。而vue的下一个大版本,也会直接使用 ts 开发。除此之外,目前几乎所有的前端热门框架,三方组件,工具方法等都通过各种方式支持了ts。
typescript 已经成为了前端开发者的必备技能之一。
而由于WebAssembly的原因,typescript可以轻松编译成WebAssembly字节码格式,ts甚至将会是JavaScript的未来。
11
代价
正如写文档一样,所有人都知道文档有无穷的好处,可是,写文档无疑带来了额外的工作量。ts也一样,带来更高可读性的同时,必然会带来更多的代码量。
总体来说,我们需要手写的额外的代码量并不少。
但是根据我的工作经验,这些额外的工作量,并不会影响我们的开发进度,反而因为减少了错误,大大增加了开发效率。所以建议大家,接受这样的代码。