Skip to content

Commit d5c972e

Browse files
committed
完成新版第一章:什么是 TypeScript
1 parent 84bf497 commit d5c972e

8 files changed

+219
-30
lines changed

assets/what-is-typescript-react.png

86.5 KB
Loading

assets/what-is-typescript-vscode.png

94.9 KB
Loading

assets/what-is-typescript-vue.png

105 KB
Loading

assets/why-typescript-airbnb.png

1.49 MB
Loading

assets/why-typescript-bugs.png

128 KB
Loading

assets/why-typescript-tip.png

25.4 KB
Loading

introduction/what-is-typescript.md

Lines changed: 160 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,180 @@
11
# 什么是 TypeScript
22

3-
首先,我对 TypeScript 的理解如下:
3+
> Typed JavaScript at Any Scale.
4+
> 添加了类型系统的 JavaScript,适用于任何规模的项目。
45
5-
[TypeScript][] 是 JavaScript 的一个超集,主要提供了**类型系统****对 ES6 的支持**,它由 Microsoft 开发,代码[开源于 GitHub](https://github.com/Microsoft/TypeScript)
6+
以上描述是官网<sup>[[1]](#link-1)</sup>对于 TypeScript 的定义
67

7-
其次引用[官网][TypeScript]的定义:
8+
它强调了 TypeScript 的两个最重要的特性——类型系统、适用于任何规模。
89

9-
> TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source.
10+
## TypeScript 的特性
1011

11-
翻译成中文即是:
12+
### 类型系统
1213

13-
> TypeScript 是 JavaScript 的类型的超集,它可以编译成纯 JavaScript。编译出来的 JavaScript 可以运行在任何浏览器上。TypeScript 编译工具可以运行在任何服务器和任何系统上。TypeScript 是开源的
14+
TypeScript 的名字就可以看出来,「类型」是其最核心的特性
1415

15-
## 为什么选择 TypeScript
16+
我们知道,JavaScript 是一门非常灵活的编程语言:
1617

17-
[TypeScript 官网][TypeScript]列举了一些优势,不过我更愿意自己总结一下:
18+
- 它没有类型约束,一个变量可能初始化时是字符串,过一会儿又被赋值为数字。
19+
- 由于隐式类型转换的存在,有的变量的类型很难在运行前就确定。
20+
- 基于原型的面向对象编程,使得原型上的属性或方法可以在运行时被修改。
21+
- 函数是 JavaScript 中的一等公民<sup>[[2]](#link-2)</sup>,可以赋值给变量,也可以当作参数或返回值。
1822

19-
### TypeScript 增加了代码的可读性和可维护性
23+
这种灵活性就像一把双刃剑,一方面使得 JavaScript 蓬勃发展,无所不能,从 2013 年开始就一直蝉联最普遍使用的编程语言排行榜冠军<sup>[[3]](#link-3)</sup>;另一方面也使得它的代码质量参次不起,维护成本高,运行时错误多。
2024

21-
- 类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了
22-
- 可以在编译阶段就发现大部分错误,这总比在运行时候出错好
23-
- 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、代码重构等
25+
而 TypeScript 的类型系统,在很大程度上弥补了 JavaScript 的缺点。
2426

25-
### TypeScript 非常包容
27+
#### TypeScript 是静态类型
2628

27-
- TypeScript 是 JavaScript 的超集,`.js` 文件可以直接重命名为 `.ts` 即可
28-
- 即使不显式的定义类型,也能够自动做出[类型推论](../basics/type-inference.md)
29-
- TypeScript 的类型系统是图灵完备的,可以定义从简单到复杂的几乎一切类型
30-
- 即使 TypeScript 编译报错,也可以生成 JavaScript 文件
31-
- 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取
29+
类型系统按照「类型检查的时机」来分类,可以分为动态类型和静态类型。
3230

33-
### TypeScript 拥有活跃的社区
31+
动态类型是指在运行时才会进行类型检查,这种语言的类型错误往往会导致运行时错误。JavaScript 是一门解释型语言<sup>[[4]](#link-4)</sup>,没有编译阶段,所以它是动态类型,以下这段代码在运行时才会报错:
3432

35-
- 大部分第三方库都有提供给 TypeScript 的类型定义文件
36-
- Angular、Vue、VS Code、Ant Design 等等耳熟能详的项目都是使用 TypeScript 编写的
37-
- TypeScript 拥抱了 ES6 规范,支持 ESNext 草案中处于第三阶状态(Stage 3)的特性
33+
```js
34+
let foo = 1;
35+
foo.split(' ');
36+
// Uncaught TypeError: foo.split is not a function
37+
// 运行时会报错(foo.split 不是一个函数),造成线上 bug
38+
```
3839

39-
### TypeScript 的缺点
40+
静态类型是指编译阶段就能确定每个变量的类型,这种语言的类型错误往往会导致语法错误。TypeScript 在运行前需要先编译为 JavaScript,而在编译阶段就会进行类型检查,所以 **TypeScript 是静态类型**,这段 TypeScript 代码在编译阶段就会报错了:
4041

41-
任何事物都是有两面性的,我认为 TypeScript 的弊端在于:
42+
```ts
43+
let foo = 1;
44+
foo.split(' ');
45+
// Property 'split' does not exist on type 'number'.
46+
// 编译时会报错(数字没有 split 方法),无法通过编译
47+
```
4248

43-
- 有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的概念
44-
- 短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需要长期维护的项目,TypeScript 能够减少其维护成本
45-
- 集成到构建流程需要一些工作量
46-
- 可能和一些库结合的不是很完美
49+
你可能会奇怪,这段 TypeScript 代码看上去和 JavaScript 没有什么区别呀。
4750

48-
大家可以根据自己团队和项目的情况判断是否需要使用 TypeScript。
51+
没错!大部分 JavaScript 代码都只需要经过少量的修改(或者完全不用修改)就变成 TypeScript 代码,这得益于 TypeScript 强大的[类型推论][],即使不去手动声明变量 `foo` 的类型,也能在变量初始化时自动推论出它是一个 `number` 类型
4952

50-
[TypeScript]: http://www.typescriptlang.org/
53+
完整的 TypeScript 代码是这样的:
54+
55+
```ts
56+
let foo: number = 1;
57+
foo.split(' ');
58+
// Property 'split' does not exist on type 'number'.
59+
// 编译时会报错(数字没有 split 方法),无法通过编译
60+
```
61+
62+
#### TypeScript 是弱类型
63+
64+
类型系统按照「是否允许隐式类型转换」来分类,可以分为强类型和弱类型。
65+
66+
以下这段代码不管是在 JavaScript 中还是在 TypeScript 中都是可以正常运行的,运行时数字 `1` 会被隐式类型转换为字符串 `'1'`,加号 `+` 被识别为字符串拼接,所以打印出结果是字符串 `'11'`
67+
68+
```js
69+
console.log(1 + '1');
70+
// 打印出字符串 '11'
71+
```
72+
73+
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性,所以**它们都是弱类型**
74+
75+
作为对比,Python 是强类型,以下代码会在运行时报错:
76+
77+
```py
78+
print(1 + '1')
79+
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
80+
```
81+
82+
若要修复该错误,需要进行强制类型转换:
83+
84+
```py
85+
print(str(1) + '1')
86+
# 打印出字符串 '11'
87+
```
88+
89+
> 强/弱是相对的,Python 在处理整型和浮点型相加时,会将整型隐式转换为浮点型,但是这并不影响 Python 是强类型的结论,因为大部分情况下 Python 并不会进行隐式类型转换。相比而言,JavaScript 和 TypeScript 中不管加号两侧是什么类型,都可以通过隐式类型转换计算出一个结果——而不是报错——所以 JavaScript 和 TypeScript 都是弱类型。
90+
91+
> 虽然 TypeScript 不限制加号两侧的类型,但是我们可以借助 TypeScript 提供的类型系统,以及 ESLint 提供的代码检查功能,来限制加号两侧必须同为数字或同为字符串<sup>[[5]](#link-5)</sup>。这在一定程度上使得 TypeScript 向「强类型」更近一步了——当然,这种限制是可选的。
92+
93+
这样的类型系统体现了 TypeScript 的核心设计理念<sup>[[6]](#link-6)</sup>:在完整保留 JavaScript 运行时行为的基础上,通过引入静态类型系统来提高代码的可维护性,减少可能出现的 bug。
94+
95+
### 适用于任何规模
96+
97+
TypeScript 非常适用于大型项目——这是显而易见的,类型系统可以为大型项目带来更高的可维护性,以及更少的 bug。
98+
99+
在中小型项目中推行 TypeScript 的最大障碍就是认为使用 TypeScript 需要写额外的代码,降低开发效率。但事实上,由于有[类型推论][],大部分类型都不需要手动声明了。相反,TypeScript 增强了编辑器(IDE)的功能,包括代码补全、接口提示、跳转到定义、代码重构等,这在很大程度上提高了开发效率。而且 TypeScript 有近百个[编译选项][],如果你认为类型检查过于严格,那么可以通过修改编译选项来降低类型检查的标准。
100+
101+
TypeScript 还可以和 JavaScript 共存。这意味着如果你有一个使用 JavaScript 开发的旧项目,又想使用 TypeScript 的特性,那么你不需要急着把整个项目都迁移到 TypeScript,你可以使用 TypeScript 编写新文件,然后在后续更迭中逐步迁移旧文件。如果一些 JavaScript 文件的迁移成本太高,TypeScript 也提供了一个方案,可以让你在不修改 JavaScript 文件的前提下,编写一个[类型声明文件][],实现旧项目的渐进式迁移。
102+
103+
事实上,就算你从来没学习过 TypeScript,你也可能已经在不知不觉中使用到了 TypeScript——在 VSCode 编辑器中编写 JavaScript 时,代码补全和接口提示等功能就是通过 TypeScript Language Service 实现的<sup>[[7]](#link-7)</sup>:
104+
105+
![what-is-typescript-vscode](../assets/what-is-typescript-vscode.png)
106+
107+
一些第三方库原生支持了 TypeScript,在使用时就能获得代码补全了,比如 Vue 3.0<sup>[[8]](#link-8)</sup>:
108+
109+
![what-is-typescript-vue](../assets/what-is-typescript-vue.png)
110+
111+
有一些第三方库原生不支持 TypeScript,但是可以通过安装社区维护的类型声明库<sup>[[9]](#link-9)</sup>(比如通过运行 `npm install --save-dev @types/react` 来安装 React 的类型声明库)来获得代码补全能力——不管是在 JavaScript 项目中还是在 TypeScript 中项目中都是支持的:
112+
113+
![what-is-typescript-react](../assets/what-is-typescript-react.png)
114+
115+
由此可见,TypeScript 的发展已经深入到前端社区的方方面面了,任何规模的项目都或多或少得到了 TypeScript 的支持。
116+
117+
### 与标准同步发展
118+
119+
TypeScript 的另一个重要的特性就是坚持与 ECMAScript 标准<sup>[[10]](#link-10)</sup>同步发展。
120+
121+
ECMAScript 是 JavaScript 核心语法的标准,自 2015 年起,每年都会发布一个新版本,包含一些新的语法。
122+
123+
一个新的语法从提案到变成正式标准,需要经历以下几个阶段:
124+
125+
- Stage 0:展示阶段,仅仅是提出了讨论、想法,尚未正式提案。
126+
- Stage 1:征求意见阶段,提供抽象的 API 描述,讨论可行性,关键算法等。
127+
- Stage 2:草案阶段,使用正式的规范语言精确描述其语法和语义。
128+
- Stage 3:候选人阶段,语法的设计工作已完成,需要浏览器、Node.js 等环境支持,搜集用户的反馈。
129+
- Stage 4:定案阶段,已准备好将其添加到正式的 ECMAScript 标准中。
130+
131+
一个语法进入到 Stage 3 阶段后,TypeScript 就会实现它。一方面,让我们可以尽早的使用到最新的语法,帮助它进入到下一个阶段;另一方面,处于 Stage 3 阶段的语法已经比较稳定了,基本不会有语法的变更,这使得我们能够放心的使用它。
132+
133+
除了实现 ECMAScript 标准之外,TypeScript 团队也推进了诸多语法提案,比如可选链操作符(`?.`)<sup>[[11]](#link-11)</sup>、空值合并操作符(`??`)<sup>[[12]](#link-12)</sup>、Throw 表达式<sup>[[13]](#link-13)</sup>、正则匹配索引<sup>[[14]](#link-14)</sup>等。
134+
135+
## 总结
136+
137+
什么是 TypeScript?
138+
139+
- TypeScript 是添加了类型系统的 JavaScript,适用于任何规模的项目。
140+
- TypeScript 是一门静态类型、弱类型的语言。
141+
- TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性。
142+
- TypeScript 可以编译为 JavaScript,然后运行在浏览器、Node.js 等任何能运行 JavaScript 的环境中。
143+
- TypeScript 拥有很多编译选项,类型检查的严格程度由你决定。
144+
- TypeScript 可以和 JavaScript 共存,这意味着 JavaScript 项目能够渐进式的迁移到 TypeScript。
145+
- TypeScript 增强了编辑器(IDE)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
146+
- TypeScript 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
147+
- TypeScript 与标准同步发展,符合最新的 ECMAScript 标准(stage 3)。
148+
149+
## 附:TypeScript 的发展历史
150+
151+
- 2012-10:微软发布了 TypeScript 第一个版本(0.8),此前已经在微软内部开发了两年。
152+
- 2014-04:TypeScript 发布了 1.0 版本。
153+
- 2014-10:Angular 发布了 2.0 版本,它是一个基于 TypeScript 开发的前端框架。
154+
- 2015-01:ts-loader 发布,webpack 可以编译 TypeScript 文件了。
155+
- 2015-04:微软发布了 Visual Studio Code,它内置了对 TypeScript 语言的支持,它自身也是用 TypeScript 开发的。
156+
- 2016-05:`@types/react` 发布,TypeScript 可以开发 React 应用了。
157+
- 2016-05:`@types/node` 发布,TypeScript 可以开发 Node.js 应用了。
158+
- 2016-09:TypeScript 发布了 2.0 版本。
159+
- 2018-06:TypeScript 发布了 3.0 版本。
160+
- 2019-02:TypeScript 宣布由官方团队来维护 typescript-eslint,以支持在 TypeScript 文件中运行 ESLint 检查。
161+
- 2020-05:Deno 发布了 1.0 版本,它是一个 JavaScript 和 TypeScript 运行时。
162+
- 2020-08:TypeScript 发布了 4.0 版本。
163+
- 2020-09:Vue 发布了 3.0 版本,官方支持 TypeScript。
164+
165+
## 参考资料
166+
167+
1. <span id="link-1">[TypeScript 官网](https://www.typescriptlang.org/)</span>
168+
2. <span id="link-2">[第 2 章: 一等公民的函数](https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch2.html) · 函数式编程指北</span>
169+
3. <span id="link-3">[StackOverflow 2020 开发者调查报告](https://insights.stackoverflow.com/survey/2020)</span>
170+
4. <span id="link-4">[斯坦福 JavaScript 第一课](https://web.stanford.edu/class/cs98si/slides/overview.html)</span>
171+
5. <span id="link-5">[TypeScript ESLint 规则 `restrict-plus-operands`](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/restrict-plus-operands.md)</span>
172+
6. <span id="link-6">[TypeScript 设计理念](https://github.com/microsoft/TypeScript/wiki/TypeScript-Design-Goals)</span>
173+
7. <span id="link-7">[Visual Studio Code 中集成了 TypeScript](https://code.visualstudio.com/docs/languages/typescript)</span>
174+
8. <span id="link-8">[Vue 3.0 支持 TypeScript](https://v3.vuejs.org/guide/typescript-support.html)</span>
175+
9. <span id="link-9">[Definitely Typed](https://github.com/DefinitelyTyped/DefinitelyTyped)——TypeScript 团队帮助维护的类型定义仓库</span>
176+
10. <span id="link-10">[ECMAScript 标准](https://tc39.es/process-document/)</span>
177+
11. <span id="link-11">[可选链操作符(`?.`](https://github.com/tc39/proposal-optional-chaining)</span>
178+
12. <span id="link-12">[空值合并操作符(`??`](https://github.com/tc39/proposal-nullish-coalescing)</span>
179+
13. <span id="link-13">[Throw 表达式](https://github.com/tc39/proposal-throw-expressions)</span>
180+
14. <span id="link-14">[正则匹配索引](https://github.com/tc39/proposal-regexp-match-indices)</span>

introduction/why-typescript.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
你可能或多或少听说过这样的言论:
3+
4+
- TypeScript 只适用于大公司的大型项目
5+
- TypeScript 适合多人协作开发,一个人维护的项目就没必要使用了
6+
- TypeScript 学习成本高,开发成本高
7+
- 旧项目是 JavaScript,所以没必要改造成 TypeScript 了
8+
9+
我想说,都 2021 年了,赶紧上车吧,绝大部分项目都应该使用 TypeScript!
10+
11+
大型项目不必多说,TypeScript 的类型系统能够集成到 IDE(或编辑器)中,通过代码补全、代码提示、跳转到定义等功能,极大的提高代码的可维护性,提高开发效率,降低 bug 率。
12+
13+
14+
15+
> 动态类型一时爽,代码重构火葬场。
16+
17+
18+
如果你没有学过 TypeScript,那么可能连这样的接口提示都看不懂了:
19+
20+
![what-is-typescript-tip](../assets/what-is-typescript-tip.png)
21+
22+
23+
24+
## 为什么选择 TypeScript
25+
26+
[TypeScript 官网][TypeScript]列举了一些优势,不过我更愿意自己总结一下:
27+
28+
### TypeScript 增加了代码的可读性和可维护性
29+
30+
- 类型系统实际上是最好的文档,大部分的函数看看类型的定义就可以知道如何使用了
31+
- 可以在编译阶段就发现大部分错误,这总比在运行时候出错好
32+
- 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、代码重构等
33+
34+
### TypeScript 非常包容
35+
36+
- TypeScript 是 JavaScript 的超集,`.js` 文件可以直接重命名为 `.ts` 即可
37+
- 即使不显式的定义类型,也能够自动做出[类型推论](../basics/type-inference.md)
38+
- TypeScript 的类型系统是图灵完备的,可以定义从简单到复杂的几乎一切类型
39+
- 即使 TypeScript 编译报错,也可以生成 JavaScript 文件
40+
- 兼容第三方库,即使第三方库不是用 TypeScript 写的,也可以编写单独的类型文件供 TypeScript 读取
41+
42+
### TypeScript 拥有活跃的社区
43+
44+
- 大部分第三方库都有提供给 TypeScript 的类型定义文件
45+
- Angular、Vue、VS Code、Ant Design 等等耳熟能详的项目都是使用 TypeScript 编写的
46+
- TypeScript 拥抱了 ES6 规范,支持 ESNext 草案中处于第三阶状态(Stage 3)的特性
47+
48+
### TypeScript 的缺点
49+
50+
任何事物都是有两面性的,我认为 TypeScript 的弊端在于:
51+
52+
- 有一定的学习成本,需要理解接口(Interfaces)、泛型(Generics)、类(Classes)、枚举类型(Enums)等前端工程师可能不是很熟悉的概念
53+
- 短期可能会增加一些开发成本,毕竟要多写一些类型的定义,不过对于一个需要长期维护的项目,TypeScript 能够减少其维护成本
54+
- 集成到构建流程需要一些工作量
55+
- 可能和一些库结合的不是很完美
56+
57+
大家可以根据自己团队和项目的情况判断是否需要使用 TypeScript。
58+
59+
StackOverflow 2020 开发者调查报告,TypeScript 击败 Python

0 commit comments

Comments
 (0)