(本文首发于ayqy.net,用️原创系列。)
一.背景
2010 – 微软团队开始开发
2012 – 第一个公开版本发布(TypeScript 0.8)
2013 – TypeScript 0.9 发布,支持泛型了
2014 – TypeScript 1.0 发布,Visual Studio 2013 默认支持 TypeScript 了。同时,源码从 CodePlex 迁移到 Github
2017 – TypeScript 2.1 发布
2018 – TypeScript 3.2 发布
TypeScript 最初是个微软内部项目,叫 Strada,致力于提升大型 JS 项目(当时内部需求是 Bing Maps、 Office Web Apps 甚至 Windows 8 apps)的可靠性和可维护性。2010 年开始开发,2012 年 10 月发布了第一个开源版本,持续迭代至今
二.目标
Application scale JavaScript development is hard.
JavaScript 最初设计目标是作为一种脚本语言,缺少一些构建大型应用必备的基础特性,如:
- 静态类型
- 结构化机制(类、模块、接口等)
类型上的缺陷导致很多错误要到运行时才能暴露出来,另一方面,缺少静态类型也是 JS 编辑体验差的主要原因,智能提示、自动补全等现代化编辑体验都是从 Visual Studio 开始的:
- 基于类型推断的智能提示
- 基于 JSDoc 的智能提示
- 基于 TypeScript 声明文件的智能提示
Application scale JavaScript development is hard, TypeScript makes it easier.
TypeScript 期望通过源码转译的方式填补这些缺陷,给 JavaScript 添上 OOP 支持(Class、Interface 等),以及可选的静态类型系统,在 ES5 时代(2010 年)建立起开发大型 JavaScript 应用的根基
此外,TypeScript 还给 JavaScript 带来了一个重要的东西,d.ts
声明文件:
Working with existing JavaScript libraries, declaration file can be written and maintained separately.
通过独立的声明文件让现有 JavaScript 类库也能拥有 TypeScript 的类型优势,在提升 JavaScript 编辑体验方面迈出了一大步
三.定位
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
有 3 个关键点:
- typed:类型化的。给 JS 补充了(可选的)静态类型
- superset of JavaScript:超集。兼容 JS,支持混用,现有的 JavaScript 类库可以直接使用
- compiles to plain JavaScript:编译到原生 JS。从 JavaScript 开始,以 JavaScript 结束
具体的:
- 从 JavaScript 开始:超集意味着所有 JavaScript 代码都是 TypeScript,语法语义都与 JavaScript 一致,复制粘贴就可以开始了
- 提供可选的静态类型、类与模块:类型不仅让 JavaScript 开发能够使用高效的开发工具和实践(如静态检查和代码重构),而且不会带来运行时的性能损耗(_静态类型仅在编译时存在_)
- 以 JavaScript 结束:TypeScript 编译产生地道的原生 JavaScript,因此支持最前沿的 JavaScript 特性,并且能在任何支持 ES3+的宿主环境中运行
可以认为TypeScript 是 JavaScript 的语法糖:
TypeScript is a syntactic sugar for JavaScript. TypeScript syntax is a superset of ECMAScript 2015 (ES2015) syntax. Every JavaScript program is also a TypeScript program.
(摘自Introduction | TypeScript Language Specification)
像类型补丁一样,能与 JavaScript 世界完美融合,这才是 TypeScript 生命力之所在:
Starts and ends with JavaScript, and optional static types, classes, modules.
并且,这一点从 TypeScript 公开发布(2012 年末)至今(2019 年初)都没有变过
四.设计原则
追求:
- 静态识别出那些可能有错的部分
- 为大段代码提供结构化机制
- 不给编译产物增加运行时开销
- 输出整洁、地道、可读的 JavaScript 代码
- 实现一种可组合、易推理的(easy to reason about)语言
- 永远和 ES 规范保持一致
- 保留所有 JavaScript 代码的运行时行为
- 避免添加表达式级的语法特性
- 一致的、完全可擦除的结构化类型系统
- 成为跨平台开发工具
- 从 TypeScript 1.0 起不要引入重大破坏性变动
拒绝:
- 完全模仿现有语言的设计,应该以 JavaScript 的行为和开发者的意愿作为语言设计指南
- 优化程序的运行时性能,应该忠实输出原生 JavaScript 代码,而不刻意优化
- 完善的或“可证明正确的”类型系统,而应该在正确性和生产力之间取得平衡
- 提供一端到另一端的(封闭)构建管道,应该让系统具有可扩展性,让编译器适用于更复杂的构建工作流
- 添加或依赖运行时类型信息,或根据类型系统的结果很长不同的代码,应该鼓励不依赖运行时信息(run-time metadata)的编程模式
- 额外提供运行时功能或类库,应该用 TypeScript 来描述现有类库
- 引入可能会让用户感到意外的行为,应该适当考虑其他常用语言所采用的模式
五.特性
类型系统
- 是 JavaScript 类型的形式化:JavaScript 类型动态系统的静态表示
- 提供类型推断与结构化类型:实际上不必都给标注上类型(类型推断能够解决一部分)
- 能够配合现有 JavaScript 类库使用:声明文件可以独立编写维护
- 不是可证明的类型安全(provably type safe):类型只反映意图,并不提供保证
最重要的是,静态类型仅在编译时存在:
In the JavaScript output, all type annotations have been erased.
例如:
// TypeScript
function f(s: string) {
return s;
}
// 编译得到的JavaScript,类型标注统统擦掉
function f(s) {
return s;
}
另外,TypeScript 虽然提供了静态类型系统,并在编译时严格检查,但并不像Haskell 类型系统一样可证明,可推理。因此,TypeScript 类型系统更多地只是作为 JavaScript 的静态类型补丁,像注释一样体现“意图”,并不保证安全
类与模块
- 可扩展的应用结构化机制:类、模块和接口支持定义组件间的明确联系
- 遵从最新标准:类、模块和箭头函数语法都与 ES6 标准一致
- 也支持业界主流模块系统:如 CommonJS 和 AMD 模块
注意,模块的语法规则与 ES 标准一致,但在加载机制上存在差异,具体见Module Resolution
六.生态
- (开源)编译器:typescript
- 工具:IDE 支持(VS、VSCode、Sublime、WebStorm、Vim 等)、Playground
- 类型库:DefinitelyTyped
- 规范:TypeScript Language Specification
- 样板项目:Samples、Community Samples
- 案例:GitHub TypeScript 项目(包括 Angular、ant-design 等)
参考资料
- TypeScript
- TypeScript Design Goals
- Anders Hejlsberg: Introducing TypeScript:TypeScript 公开发布演讲
- TypeScript:上面演讲对应的 PPT
- Who built Microsoft TypeScript and why
- TypeScript