一、ts的静态检查
参考为什么要使用TypeScript?有哪些情景请简单介绍一下,或者来个例子?
TS对JS的改进主要是静态类型检查,静态类型检查有何意义?标准答案是“静态类型更有利于构建大型应用”。为什么静态类型有利于构建大型应用?我总结,利在两点。
1.静态类型检查可以做到early fail
即你编写的代码即使没有被执行到,一旦你编写代码时发生类型不匹配,语言在编译阶段(解释执行也一样,可以在运行前)即可发现。针对大型应用,测试调试分支覆盖困难,很多代码并不一定能够在所有条件下执行到。而假如你的代码简单到任何改动都可以从UI体现出来,这确实跟大型应用搭不上关系,那么静态类型检查确实没什么作用。
举例参考随着 JavaScript 越来越完善,还有必要学习 TypeScript 吗? - 动感小菜刀的回答 - 知乎
console.log('index', index); // output is 1
for (var i = index; i <= 2; i++) {
console.log("i", i);
}
/* two lines printed from the inside console.log, result:
* i 1
* i 2
*/
for (var i = index + 1; i <= 2; i++) {
console.log("i", i);
}
/* nothing printed from the inside console.log */
第二个for loop结果显然不正确,因为应该loop一次打印出一行 "i 2"。但事实上运行结果却什么都没打印出来。原因是变量index是string “1”,而不是number 1。 "1"+1 = "11","11" < 2 是false我觉得这是个很好且简短的例子体现出Type Check的重要性。如果用typescript的话transpile过程中会报错,text editor也会高亮错误,因为“string + number”相加是不合理的
2.类型就是最好的注释
静态类型对阅读代码是友好的,比如我们举个例子 jQuery API Documentation 这是大家都非常喜欢用的jQuery.ajax,在这份文档中,详尽地解释了类型为object的唯一一个参数settings,它是如此之复杂,如果没有文档,我们只看这个函数声明的话,根本不可能有人把这个用法猜对。
针对大型应用,方法众多,调用关系复杂,不可能每个函数都有人编写细致的文档,所以静态类型就是非常重要的提示和约束。而假如你的代码像jQuery这样所有函数基本全是API,根本没什么内部函数,而且逻辑关系看起来显而易见,这确实跟大型应用搭不上关系,那么静态类型对阅读代码确实也没什么帮助。
总的来说,现代编程语言设计,很多特性已经有非常成熟的理论支持了,如果我们重视计算机基础,那么一些语言的适用场景就像是拼积木,可以用几句话概括。像是TS对JS这样,只是单一特性变化。
二、rename
参考有了Babel的话还在使用TypeScript的优势在哪?
随便说一点公司现在的前端项目大概有十几万行代码,各种从后端拿到的数据类型有上百种以前后端接口一改,要改字段,瞬间懵逼。全局搜索,一个个改,各种牵扯到的东西改下来再测试一顿估计小半天没了。用了 TypeScript 之后,把数据对应的 interface 改掉,然后重新编译一次,把编译失败的地方全部改掉就好了。而且在优秀的 TypeScript 架构中,业务开发基本不需要写类型,所有外部输入的类型都可以自动拿到,只需要把一些 local variable 和 output 的类型定义一下就好了,基本跟手写 ES 6 没有区别。写代码的过程中各种错误在越早期修改的成本就越低。试想没有静态检查跑一遍代码进某个奇怪的 case 才能复现的错误在写代码时期就直接给你的个错误提示,将是多么省时省力省钱。
对一个传统的js程序,你执行一次最简单的rename重构试试?除非是局部变量,否则我是没那个胆量。我以前这么改的时候它连node_modules中的东西都给我改了,后来再也不敢做超出局部变量范围的重构了。而ts用了一年多了,java中能做的大部分重构我都做过,一次都还没有给我惹祸。当然,如果你都没做过重构,任何程序都是一次写出来就完美,我觉得你肯定是Jeff Dean,来知乎未免太屈才了
三、【校招面试】关于Typescript和ES6的对比?
具体情况:回忆起当时的面试场景,确实很大一部分时间是关于这个问题的(简历里写了自己技术栈主要用TS写react)我答了很多,包括从 静态类型可以帮助我们在运行前发现一部分潜在的bug,帮助IDE做代码提示,更容易让学JAVA、C++的开发者开发前端。但面试官始终觉得我没有说出他想听到的答案,整个交流的过程中,面试官说了许多让我很不认同的点,包括他觉得代码检查可以有ESlint,智能提示是IDE是事和typescript本身无关,然后他说TS这种强类型的类型限制对项目开发确实有好处,但这都不是他想听到的点。说实话,我当时有些无奈的,我觉得ESlint这种只是代码风格和低级的错误检查,给动态语言的代码提示是一件很困难的事情,所以需要静态类型的帮助,我还和他指出了TS严格来说是静态类型并不是强类型。
第二通电话里,我和他又聊了这个事情,他觉得TS最大的价值是引入了 接口、类、继承的编程思想,这就是他想听到的答案,我特别迷惑,我问了他 ES6的语法里也有类和继承,这应该不是TS的特性吧,他的回答是 ES6的类和TS的类的实现完全不一样,然后让我回去好好看看。他觉得我太自信了,很多东西还不是很懂。说真的,我特别无奈,TS是要通过tsc转换的,可以直接转到ES5或是ES6,这本身只是语法糖和类的思想的问题,为什么会有完全不一样这种说法呢。而且,我电话里还讲了本质上我觉得TS和ES6并不是两个完全对立的东西,ES指的应该是关于语言的语法规范,TS完全就兼容ES各个版本的语法,所以才说TS是JS的超集。而面试官始终坚持TS和ES6是两种完全不一样的开发模式,他说他本身更多的是用ES6去开发,不怎么写TS,他觉得我太自信了,很多东西还要去学习。我真的特别无奈,我想知道对于这个问题到底应该怎么样回答。
不考虑「面试」这个问题本身的话,题主的理解确实是基本正确的,并且「面试官」的理解问题很多(假设题主的引述真实的话)。
1.包括他觉得代码检查可以有ESlintESlint
检查的是代码规范,而非程序逻辑本身(假设语法正确的情况下)。
2.智能提示是IDE是事和typescript本身无关
很不巧,TypeScript 自带了完备的 Language Service(Microsoft/TypeScript),功能包括但不仅限于什么时候报什么错,输了什么之后给什么提示,选择了某个提示之后自动补全什么内容。IDE 除了简单整合一下 UI 之外真的没什么事。相反,IDE 如果自己做效果还可能更渣。
3.然后他说TS这种强类型的类型限制对项目开发确实有好处
TypeScript 不是「强类型」,是「静态类型检查」的「弱类型」。
4.他觉得TS最大的价值是引入了 接口、类、继承的编程思想
「类」和「继承」都不是 TypeScript 引入的,直接作为 JavaScript 的超集包含进来了而已。TypeScript 的 interface 是 Structural 的(其实连 class 也是 Structural 的),只要恰好长一样就是相同类型。interface 的引入就只是方便 Duck Typing 下的检查而已,和 Java、C# 那样的 Nominal 的 interface 差别明显。另外,除了 Duck Typing 外,JavaScript 并不是没有「面向接口」编程的实践,实际上 ES2015 中 Symbol 的一个重要作用就是承担 interface 的职责,比如 Symbol.iterator,带有这个属性就等价于「面向接口」编程中的实现了 Iterable 这个 interface,从而能够被 for-of 使用。现在的 Proposal 里面还有 Symbol.asyncIterator 和 Symbol.observable,当然很显然的就是定义了 AsyncIterable 和 Observable 这两个 interface 出来,只是没有单独设置 interface 这个关键词而已。
事实上 interface 和 implements 也已经是 JavaScript 中的 Future Reserved Words,未来很有可能会引入到规范中,目前在 ES Discuss 中对于引入 interface 也有广泛讨论,但是阻力也不小。
5.他的回答是 ES6的类和TS的类的实现完全不一样,然后让我回去好好看看让他回去自己好好看看
TypeScript 的 Design Goals(Microsoft/TypeScript),然后看实现的时候记得把 target 设成 esnext,能剩下的东西都不是 TypeScript 的东西。
6.而面试官始终坚持TS和ES6是两种完全不一样的开发模式
ES6 并非只有一种开发模式,同样的 TypeScript 也并非只有一种开发模式。最大的可能是本身对 JavaScript 不了解所以误认为 TypeScript 里文档里给的概念就是 TypeScript 的概念。TypeScript 只是为 JavaScript 中本身就存在的使用方式提供了对应的类型标注,所有在 TypeScript 中能够使用的开发模式,在 JavaScript 中一定是本身就存在的。要认为 TypeScript 能产生和 JavaScript 完全不一样的开发模式,那只能认为是完全不了解 JavaScript。
四、TS遇到的问题
参考你为什么不使用 TypeScript?
注意TS没坑,框架没坑,TS+框架会有很多坑你必须学习框架+全家桶的各种暴露出来的d.ts(还好用的是React,生态良好,生态差的在下一条出现),重新配置webpack,并解决各种冲突,比如在webpack中设置了src为@方便我们引入文件,然而Typescript不识别会报错,你需要解决这种冲突,此类冲突很多,还有如果TS彻底替代babel会出问题,比如不能享受babel-plugin-import这种按需引入的Babel插件了,最好的方法是TS+Babel,这又是额外的复杂度,再比如prettier美化插件,虽然支持了TS但是会出现各种各样的花式美化,还有各种各样的坑爹的地方就不提了,需要有一段很恶心的过程去一点点踩坑,我对那段的记忆反正是痛苦的,但是醉心于TS第一条提到的优点,还是把这shi吃了。。。而且还时不时踩到shi。。对应题主的问题,我当初有放弃的想法,就是因为TS与框架的结合方面会出现大量细枝末节的问题,这是阻止人们使用的一大障碍
TS到底适合什么场景我个人认为1. 中大型项目,需要长期维护的项目,底层库or框架2.上一条的前提是,项目主要依赖的类库对TS支持良好,最好有业界的先行案例所以用一些冷门框架或者小项目的时候我是不用TS的,TS没问题,框架也没问题,框架+TS会有很多问题。