-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathmigrating-from-javascript.html
More file actions
471 lines (418 loc) · 48 KB
/
migrating-from-javascript.html
File metadata and controls
471 lines (418 loc) · 48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
<!DOCTYPE HTML>
<html lang="zh-Hans" class="light" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>从 JavaScript 迁移到 TypeScript - TypeScript 使用指南手册</title>
<!-- Custom HTML head -->
<meta name="description" content="TypeScript Handbook 中文翻译。">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="../../favicon.svg">
<link rel="shortcut icon" href="../../favicon.png">
<link rel="stylesheet" href="../../css/variables.css">
<link rel="stylesheet" href="../../css/general.css">
<link rel="stylesheet" href="../../css/chrome.css">
<link rel="stylesheet" href="../../css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../../fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../../highlight.css">
<link rel="stylesheet" href="../../tomorrow-night.css">
<link rel="stylesheet" href="../../ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body class="sidebar-visible no-js">
<div id="body-container">
<!-- Provide site root to javascript -->
<script>
var path_to_root = "../../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('light')
html.classList.add(theme);
var body = document.querySelector('body');
body.classList.remove('no-js')
body.classList.add('js');
</script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
var body = document.querySelector('body');
var sidebar = null;
var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
}
sidebar_toggle.checked = sidebar === 'visible';
body.classList.remove('sidebar-visible');
body.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="../../PREFACE.html">前言</a></li><li class="chapter-item expanded affix "><li class="part-title">快速上手</li><li class="chapter-item expanded "><a href="../../zh/tutorials/index.html"><strong aria-hidden="true">1.</strong> 快速上手</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/tutorials/typescript-in-5-minutes.html"><strong aria-hidden="true">1.1.</strong> 5 分钟了解 TypeScript</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/asp.net-core.html"><strong aria-hidden="true">1.2.</strong> ASP.NET Core</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/asp.net-4.html"><strong aria-hidden="true">1.3.</strong> ASP.NET 4</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/gulp.html"><strong aria-hidden="true">1.4.</strong> Gulp</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/knockout.html"><strong aria-hidden="true">1.5.</strong> Knockout.js</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/react-and-webpack.html"><strong aria-hidden="true">1.6.</strong> React 与 webpack</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/react.html"><strong aria-hidden="true">1.7.</strong> React</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/angular-2.html"><strong aria-hidden="true">1.8.</strong> Angular 2</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/migrating-from-javascript.html" class="active"><strong aria-hidden="true">1.9.</strong> 从 JavaScript 迁移到 TypeScript</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册</li><li class="chapter-item expanded "><a href="../../zh/handbook/index.html"><strong aria-hidden="true">2.</strong> 手册</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/handbook/basic-types.html"><strong aria-hidden="true">2.1.</strong> 基础类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/interfaces.html"><strong aria-hidden="true">2.2.</strong> 接口</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/functions.html"><strong aria-hidden="true">2.3.</strong> 函数</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/literal-types.html"><strong aria-hidden="true">2.4.</strong> 字面量类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/unions-and-intersections.html"><strong aria-hidden="true">2.5.</strong> 联合类型和交叉类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/classes.html"><strong aria-hidden="true">2.6.</strong> 类</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/enums.html"><strong aria-hidden="true">2.7.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/generics.html"><strong aria-hidden="true">2.8.</strong> 泛型</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册(进阶)</li><li class="chapter-item expanded "><a href="../../zh/reference/index.html"><strong aria-hidden="true">3.</strong> 手册(进阶)</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/reference/advanced-types.html"><strong aria-hidden="true">3.1.</strong> 高级类型</a></li><li class="chapter-item expanded "><a href="../../zh/reference/utility-types.html"><strong aria-hidden="true">3.2.</strong> 实用工具类型</a></li><li class="chapter-item expanded "><a href="../../zh/reference/decorators.html"><strong aria-hidden="true">3.3.</strong> Decorators</a></li><li class="chapter-item expanded "><a href="../../zh/reference/declaration-merging.html"><strong aria-hidden="true">3.4.</strong> 声明合并</a></li><li class="chapter-item expanded "><a href="../../zh/reference/iterators-and-generators.html"><strong aria-hidden="true">3.5.</strong> Iterators 和 Generators</a></li><li class="chapter-item expanded "><a href="../../zh/reference/jsx.html"><strong aria-hidden="true">3.6.</strong> JSX</a></li><li class="chapter-item expanded "><a href="../../zh/reference/mixins.html"><strong aria-hidden="true">3.7.</strong> 混入</a></li><li class="chapter-item expanded "><a href="../../zh/reference/modules.html"><strong aria-hidden="true">3.8.</strong> 模块</a></li><li class="chapter-item expanded "><a href="../../zh/reference/module-resolution.html"><strong aria-hidden="true">3.9.</strong> 模块解析</a></li><li class="chapter-item expanded "><a href="../../zh/reference/namespaces.html"><strong aria-hidden="true">3.10.</strong> 命名空间</a></li><li class="chapter-item expanded "><a href="../../zh/reference/namespaces-and-modules.html"><strong aria-hidden="true">3.11.</strong> 命名空间和模块</a></li><li class="chapter-item expanded "><a href="../../zh/reference/symbols.html"><strong aria-hidden="true">3.12.</strong> Symbols</a></li><li class="chapter-item expanded "><a href="../../zh/reference/triple-slash-directives.html"><strong aria-hidden="true">3.13.</strong> 三斜线指令</a></li><li class="chapter-item expanded "><a href="../../zh/reference/type-compatibility.html"><strong aria-hidden="true">3.14.</strong> 类型兼容性</a></li><li class="chapter-item expanded "><a href="../../zh/reference/type-inference.html"><strong aria-hidden="true">3.15.</strong> 类型推论</a></li><li class="chapter-item expanded "><a href="../../zh/reference/variable-declarations.html"><strong aria-hidden="true">3.16.</strong> 变量声明</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册(v2)</li><li class="chapter-item expanded "><a href="../../zh/handbook-v2/index.html"><strong aria-hidden="true">4.</strong> 手册(v2)</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/handbook-v2/type-manipulation/template-literal-types.html"><strong aria-hidden="true">4.1.</strong> 模版字面量类型</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">TypeScript 声明文件(.d.ts)</li><li class="chapter-item expanded "><a href="../../zh/declaration-files/index.html"><strong aria-hidden="true">5.</strong> 如何书写声明文件</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/declaration-files/introduction.html"><strong aria-hidden="true">5.1.</strong> 介绍</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/by-example.html"><strong aria-hidden="true">5.2.</strong> 举例</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/library-structures.html"><strong aria-hidden="true">5.3.</strong> 库结构</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/templates.html"><strong aria-hidden="true">5.4.</strong> 模板</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/do-s-and-don-ts.html"><strong aria-hidden="true">5.5.</strong> 最佳实践</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/deep-dive.html"><strong aria-hidden="true">5.6.</strong> 深入</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/publishing.html"><strong aria-hidden="true">5.7.</strong> 发布</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/consumption.html"><strong aria-hidden="true">5.8.</strong> 使用</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">TypeScript for JavaScript</li><li class="chapter-item expanded "><a href="../../zh/javascript/type-checking-javascript-files.html"><strong aria-hidden="true">6.</strong> JavaScript 文件里的类型检查</a></li><li class="chapter-item expanded affix "><li class="part-title">工程配置</li><li class="chapter-item expanded "><a href="../../zh/project-config/index.html"><strong aria-hidden="true">7.</strong> 工程配置</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/project-config/tsconfig.json.html"><strong aria-hidden="true">7.1.</strong> tsconfig.json</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/project-references.html"><strong aria-hidden="true">7.2.</strong> 工程引用</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/typings-for-npm-packages.html"><strong aria-hidden="true">7.3.</strong> NPM 包的类型</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/compiler-options.html"><strong aria-hidden="true">7.4.</strong> 编译选项</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/configuring-watch.html"><strong aria-hidden="true">7.5.</strong> 配置 Watch</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/compiler-options-in-msbuild.html"><strong aria-hidden="true">7.6.</strong> 在 MSBuild 里使用编译选项</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/integrating-with-build-tools.html"><strong aria-hidden="true">7.7.</strong> 与其它构建工具整合</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/nightly-builds.html"><strong aria-hidden="true">7.8.</strong> 使用 TypeScript 的每日构建版本</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">版本发布说明(Release Notes)</li><li class="chapter-item expanded "><a href="../../zh/release-notes/index.html"><strong aria-hidden="true">8.</strong> 新增功能</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.4.html"><strong aria-hidden="true">8.1.</strong> TypeScript 5.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.3.html"><strong aria-hidden="true">8.2.</strong> TypeScript 5.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.2.html"><strong aria-hidden="true">8.3.</strong> TypeScript 5.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.1.html"><strong aria-hidden="true">8.4.</strong> TypeScript 5.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.0.html"><strong aria-hidden="true">8.5.</strong> TypeScript 5.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.9.html"><strong aria-hidden="true">8.6.</strong> TypeScript 4.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.8.html"><strong aria-hidden="true">8.7.</strong> TypeScript 4.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.7.html"><strong aria-hidden="true">8.8.</strong> TypeScript 4.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.6.html"><strong aria-hidden="true">8.9.</strong> TypeScript 4.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.5.html"><strong aria-hidden="true">8.10.</strong> TypeScript 4.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.4.html"><strong aria-hidden="true">8.11.</strong> TypeScript 4.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.3.html"><strong aria-hidden="true">8.12.</strong> TypeScript 4.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.2.html"><strong aria-hidden="true">8.13.</strong> TypeScript 4.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.1.html"><strong aria-hidden="true">8.14.</strong> TypeScript 4.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.0.html"><strong aria-hidden="true">8.15.</strong> TypeScript 4.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.9.html"><strong aria-hidden="true">8.16.</strong> TypeScript 3.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.8.html"><strong aria-hidden="true">8.17.</strong> TypeScript 3.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.7.html"><strong aria-hidden="true">8.18.</strong> TypeScript 3.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.6.html"><strong aria-hidden="true">8.19.</strong> TypeScript 3.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.5.html"><strong aria-hidden="true">8.20.</strong> TypeScript 3.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.4.html"><strong aria-hidden="true">8.21.</strong> TypeScript 3.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.3.html"><strong aria-hidden="true">8.22.</strong> TypeScript 3.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.2.html"><strong aria-hidden="true">8.23.</strong> TypeScript 3.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.1.html"><strong aria-hidden="true">8.24.</strong> TypeScript 3.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.0.html"><strong aria-hidden="true">8.25.</strong> TypeScript 3.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.9.html"><strong aria-hidden="true">8.26.</strong> TypeScript 2.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.8.html"><strong aria-hidden="true">8.27.</strong> TypeScript 2.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.7.html"><strong aria-hidden="true">8.28.</strong> TypeScript 2.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.6.html"><strong aria-hidden="true">8.29.</strong> TypeScript 2.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.5.html"><strong aria-hidden="true">8.30.</strong> TypeScript 2.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.4.html"><strong aria-hidden="true">8.31.</strong> TypeScript 2.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.3.html"><strong aria-hidden="true">8.32.</strong> TypeScript 2.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.2.html"><strong aria-hidden="true">8.33.</strong> TypeScript 2.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.1.html"><strong aria-hidden="true">8.34.</strong> TypeScript 2.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.0.html"><strong aria-hidden="true">8.35.</strong> TypeScript 2.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.8.html"><strong aria-hidden="true">8.36.</strong> TypeScript 1.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.7.html"><strong aria-hidden="true">8.37.</strong> TypeScript 1.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.6.html"><strong aria-hidden="true">8.38.</strong> TypeScript 1.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.5.html"><strong aria-hidden="true">8.39.</strong> TypeScript 1.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.4.html"><strong aria-hidden="true">8.40.</strong> TypeScript 1.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.3.html"><strong aria-hidden="true">8.41.</strong> TypeScript 1.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.1.html"><strong aria-hidden="true">8.42.</strong> TypeScript 1.1</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">破坏性改动(Breaking Changes)</li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/index.html"><strong aria-hidden="true">9.</strong> Breaking Changes</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.6.html"><strong aria-hidden="true">9.1.</strong> TypeScript 3.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.5.html"><strong aria-hidden="true">9.2.</strong> TypeScript 3.5</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.4.html"><strong aria-hidden="true">9.3.</strong> TypeScript 3.4</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.2.html"><strong aria-hidden="true">9.4.</strong> TypeScript 3.2</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.1.html"><strong aria-hidden="true">9.5.</strong> TypeScript 3.1</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.0.html"><strong aria-hidden="true">9.6.</strong> TypeScript 3.0</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.9.html"><strong aria-hidden="true">9.7.</strong> TypeScript 2.9</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.8.html"><strong aria-hidden="true">9.8.</strong> TypeScript 2.8</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.7.html"><strong aria-hidden="true">9.9.</strong> TypeScript 2.7</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.6.html"><strong aria-hidden="true">9.10.</strong> TypeScript 2.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.4.html"><strong aria-hidden="true">9.11.</strong> TypeScript 2.4</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.3.html"><strong aria-hidden="true">9.12.</strong> TypeScript 2.3</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.2.html"><strong aria-hidden="true">9.13.</strong> TypeScript 2.2</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.1.html"><strong aria-hidden="true">9.14.</strong> TypeScript 2.1</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.0.html"><strong aria-hidden="true">9.15.</strong> TypeScript 2.0</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.8.html"><strong aria-hidden="true">9.16.</strong> TypeScript 1.8</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.7.html"><strong aria-hidden="true">9.17.</strong> TypeScript 1.7</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.6.html"><strong aria-hidden="true">9.18.</strong> TypeScript 1.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.5.html"><strong aria-hidden="true">9.19.</strong> TypeScript 1.5</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.4.html"><strong aria-hidden="true">9.20.</strong> TypeScript 1.4</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<!-- Track and set sidebar scroll position -->
<script>
var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
sidebarScrollbox.addEventListener('click', function(e) {
if (e.target.tagName === 'A') {
sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
}
}, { passive: true });
var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
sessionStorage.removeItem('sidebar-scroll');
if (sidebarScrollTop) {
// preserve sidebar scroll position when navigating via links within sidebar
sidebarScrollbox.scrollTop = sidebarScrollTop;
} else {
// scroll sidebar to current active section when navigating via "next/previous chapter" buttons
var activeSection = document.querySelector('#sidebar .active');
if (activeSection) {
activeSection.scrollIntoView({ block: 'center' });
}
}
</script>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">TypeScript 使用指南手册</h1>
<div class="right-buttons">
<a href="../../print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="从javascript迁移到typescript"><a class="header" href="#从javascript迁移到typescript">从JavaScript迁移到TypeScript</a></h1>
<p>TypeScript不是凭空存在的。 它从JavaScript生态系统和大量现存的JavaScript而来。 将JavaScript代码转换成TypeScript虽乏味却不是难事。 接下来这篇教程将教你怎么做。 在开始转换TypeScript之前,我们假设你已经理解了足够多本手册里的内容。</p>
<p>如果你打算要转换一个React工程,推荐你先阅读<a href="https://github.com/Microsoft/TypeScript-React-Conversion-Guide#typescript-react-conversion-guide">React转换指南</a>。</p>
<h2 id="设置目录"><a class="header" href="#设置目录">设置目录</a></h2>
<p>如果你在写纯JavaScript,你大概是想直接运行这些JavaScript文件, 这些文件存在于<code>src</code>,<code>lib</code>或<code>dist</code>目录里,它们可以按照预想运行。</p>
<p>若如此,那么你写的纯JavaScript文件将做为TypeScript的输入,你将要运行的是TypeScript的输出。 在从JS到TS的转换过程中,我们会分离输入文件以防TypeScript覆盖它们。 你也可以指定输出目录。</p>
<p>你可能还需要对JavaScript做一些中间处理,比如合并或经过Babel再次编译。 在这种情况下,你应该已经有了如下的目录结构。</p>
<p>那么现在,我们假设你已经设置了这样的目录结构:</p>
<pre><code class="language-text">projectRoot
├── src
│ ├── file1.js
│ └── file2.js
├── built
└── tsconfig.json
</code></pre>
<p>如果你在<code>src</code>目录外还有<code>tests</code>文件夹,那么在<code>src</code>里可以有一个<code>tsconfig.json</code>文件,在<code>tests</code>里还可以有一个。</p>
<h2 id="书写配置文件"><a class="header" href="#书写配置文件">书写配置文件</a></h2>
<p>TypeScript使用<code>tsconfig.json</code>文件管理工程配置,例如你想包含哪些文件和进行哪些检查。 让我们先创建一个简单的工程配置文件:</p>
<pre><code class="language-javascript">{
"compilerOptions": {
"outDir": "./built",
"allowJs": true,
"target": "es5"
},
"include": [
"./src/**/*"
]
}
</code></pre>
<p>这里我们为TypeScript设置了一些东西:</p>
<ol>
<li>读取所有可识别的<code>src</code>目录下的文件(通过<code>include</code>)。</li>
<li>接受JavaScript做为输入(通过<code>allowJs</code>)。</li>
<li>生成的所有文件放在<code>built</code>目录下(通过<code>outDir</code>)。</li>
<li>将JavaScript代码降级到低版本比如ECMAScript 5(通过<code>target</code>)。</li>
</ol>
<p>现在,如果你在工程根目录下运行<code>tsc</code>,就可以在<code>built</code>目录下看到生成的文件。 <code>built</code>下的文件应该与<code>src</code>下的文件相同。 现在你的工程里的TypeScript已经可以工作了。</p>
<h3 id="早期收益"><a class="header" href="#早期收益">早期收益</a></h3>
<p>现在你已经可以看到TypeScript带来的好处,它能帮助我们理解当前工程。 如果你打开像<a href="https://code.visualstudio.com">VS Code</a>或<a href="https://visualstudio.com">Visual Studio</a>这样的编译器,你就能使用像自动补全这样的工具。 你还可以配置如下的选项来帮助查找BUG:</p>
<ul>
<li><code>noImplicitReturns</code> 会防止你忘记在函数末尾返回值。</li>
<li><code>noFallthroughCasesInSwitch</code> 会防止在<code>switch</code>代码块里的两个<code>case</code>之间忘记添加<code>break</code>语句。</li>
</ul>
<p>TypeScript还能发现那些执行不到的代码和标签,你可以通过设置<code>allowUnreachableCode</code>和<code>allowUnusedLabels</code>选项来禁用。</p>
<h2 id="与构建工具进行集成"><a class="header" href="#与构建工具进行集成">与构建工具进行集成</a></h2>
<p>在你的构建管道中可能包含多个步骤。 比如为每个文件添加一些内容。 每种工具的使用方法都是不同的,我们会尽可能的包涵主流的工具。</p>
<h3 id="gulp"><a class="header" href="#gulp">Gulp</a></h3>
<p>如果你在使用时髦的Gulp,我们已经有一篇关于<a href="gulp.html">使用Gulp</a>结合TypeScript并与常见构建工具Browserify,Babelify和Uglify进行集成的教程。 请阅读这篇教程。</p>
<h3 id="webpack"><a class="header" href="#webpack">Webpack</a></h3>
<p>Webpack集成非常简单。 你可以使用<code>awesome-typescript-loader</code>,它是一个TypeScript的加载器,结合<code>source-map-loader</code>方便调试。 运行:</p>
<pre><code class="language-text">npm install awesome-typescript-loader source-map-loader
</code></pre>
<p>并将下面的选项合并到你的<code>webpack.config.js</code>文件里:</p>
<pre><code class="language-javascript">module.exports = {
entry: "./src/index.ts",
output: {
filename: "./dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" }
],
preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
// Other options...
};
</code></pre>
<p>要注意的是,<code>awesome-typescript-loader</code>必须在其它处理<code>.js</code>文件的加载器之前运行。</p>
<p>这与另一个TypeScript的Webpack加载器<a href="https://github.com/TypeStrong/ts-loader">ts-loader</a>是一样的。 你可以到<a href="https://github.com/s-panferov/awesome-typescript-loader#differences-between-ts-loader">这里</a>了解两者之间的差别。</p>
<p>你可以在<a href="react-and-webpack.html">React和Webpack教程</a>里找到使用Webpack的例子。</p>
<h2 id="转换到typescript文件"><a class="header" href="#转换到typescript文件">转换到TypeScript文件</a></h2>
<p>到目前为止,你已经做好了使用TypeScript文件的准备。 第一步,将<code>.js</code>文件重命名为<code>.ts</code>文件。 如果你使用了JSX,则重命名为<code>.tsx</code>文件。</p>
<p>第一步达成? 太棒了! 你已经成功地将一个文件从JavaScript转换成了TypeScript!</p>
<p>当然了,你可能感觉哪里不对劲儿。 如果你在支持TypeScript的编辑器(或运行<code>tsc --pretty</code>)里打开了那个文件,你可能会看到有些行上有红色的波浪线。 你可以把它们当做在Microsoft Word里看到的红色波浪线一样。 但是TypeScript仍然会编译你的代码,就好比Word还是允许你打印你的文档一样。</p>
<p>如果对你来说这种行为太随便了,你可以让它变得严格些。 如果,你_不想_在发生错误的时候,TypeScript还会被编译成JavaScript,你可以使用<code>noEmitOnError</code>选项。 从某种意义上来讲,TypeScript具有一个调整它的严格性的刻度盘,你可以将指针拔动到你想要的位置。</p>
<p>如果你计划使用可用的高度严格的设置,最好现在就启用它们(查看<a href="migrating-from-javascript.html#getting-stricter-checks">启用严格检查</a>)。 比如,如果你不想让TypeScript将没有明确指定的类型默默地推断为<code>any</code>类型,可以在修改文件之前启用<code>noImplicitAny</code>。 你可能会觉得这有些过度严格,但是长期收益很快就能显现出来。</p>
<h3 id="去除错误"><a class="header" href="#去除错误">去除错误</a></h3>
<p>我们提到过,若不出所料,在转换后将会看到错误信息。 重要的是我们要逐一的查看它们并决定如何处理。 通常这些都是真正的BUG,但有时必须要告诉TypeScript你要做的是什么。</p>
<h4 id="由模块导入"><a class="header" href="#由模块导入">由模块导入</a></h4>
<p>首先你可能会看到一些类似<code>Cannot find name 'require'.</code>和<code>Cannot find name 'define'.</code>的错误。 遇到这种情况说明你在使用模块。 你仅需要告诉TypeScript它们是存在的:</p>
<pre><code class="language-typescript">// For Node/CommonJS
declare function require(path: string): any;
</code></pre>
<p>或</p>
<pre><code class="language-typescript">// For RequireJS/AMD
declare function define(...args: any[]): any;
</code></pre>
<p>最好是避免使用这些调用而改用TypeScript的导入语法。</p>
<p>首先,你要使用TypeScript的<code>module</code>标记来启用一些模块系统。 可用的选项有<code>commonjs</code>,<code>amd</code>,<code>system</code>,and <code>umd</code>。</p>
<p>如果代码里存在下面的Node/CommonJS代码:</p>
<pre><code class="language-javascript">var foo = require("foo");
foo.doStuff();
</code></pre>
<p>或者下面的RequireJS/AMD代码:</p>
<pre><code class="language-javascript">define(["foo"], function(foo) {
foo.doStuff();
})
</code></pre>
<p>那么可以写做下面的TypeScript代码:</p>
<pre><code class="language-typescript">import foo = require("foo");
foo.doStuff();
</code></pre>
<h4 id="获取声明文件"><a class="header" href="#获取声明文件">获取声明文件</a></h4>
<p>如果你开始做转换到TypeScript导入,你可能会遇到<code>Cannot find module 'foo'.</code>这样的错误。 问题出在没有_声明文件_来描述你的代码库。 幸运的是这非常简单。 如果TypeScript报怨像是没有<code>lodash</code>包,那你只需这样做</p>
<pre><code class="language-text">npm install -S @types/lodash
</code></pre>
<p>如果你没有使用<code>commonjs</code>模块模块选项,那么就需要将<code>moduleResolution</code>选项设置为<code>node</code>。</p>
<p>之后,你应该就可以导入<code>lodash</code>了,并且会获得精确的自动补全功能。</p>
<h4 id="由模块导出"><a class="header" href="#由模块导出">由模块导出</a></h4>
<p>通常来讲,由模块导出涉及添加属性到<code>exports</code>或<code>module.exports</code>。 TypeScript允许你使用顶级的导出语句。 比如,你要导出下面的函数:</p>
<pre><code class="language-javascript">module.exports.feedPets = function(pets) {
// ...
}
</code></pre>
<p>那么你可以这样写:</p>
<pre><code class="language-typescript">export function feedPets(pets) {
// ...
}
</code></pre>
<p>有时你会完全重写导出对象。 这是一个常见模式,这会将模块变为可立即调用的模块:</p>
<pre><code class="language-javascript">var express = require("express");
var app = express();
</code></pre>
<p>之前你可以是这样写的:</p>
<pre><code class="language-javascript">function foo() {
// ...
}
module.exports = foo;
</code></pre>
<p>在TypeScript里,你可以使用<code>export =</code>来代替。</p>
<pre><code class="language-typescript">function foo() {
// ...
}
export = foo;
</code></pre>
<h4 id="过多或过少的参数"><a class="header" href="#过多或过少的参数">过多或过少的参数</a></h4>
<p>有时你会发现你在调用一个具有过多或过少参数的函数。 通常,这是一个BUG,但在某些情况下,你可以声明一个使用<code>arguments</code>对象的函数而不需要写出所有参数:</p>
<pre><code class="language-javascript">function myCoolFunction() {
if (arguments.length == 2 && !Array.isArray(arguments[1])) {
var f = arguments[0];
var arr = arguments[1];
// ...
}
// ...
}
myCoolFunction(function(x) { console.log(x) }, [1, 2, 3, 4]);
myCoolFunction(function(x) { console.log(x) }, 1, 2, 3, 4);
</code></pre>
<p>这种情况下,我们需要利用TypeScript的函数重载来告诉调用者<code>myCoolFunction</code>函数的调用方式。</p>
<pre><code class="language-typescript">function myCoolFunction(f: (x: number) => void, nums: number[]): void;
function myCoolFunction(f: (x: number) => void, ...nums: number[]): void;
function myCoolFunction() {
if (arguments.length == 2 && !Array.isArray(arguments[1])) {
var f = arguments[0];
var arr = arguments[1];
// ...
}
// ...
}
</code></pre>
<p>我们为<code>myCoolFunction</code>函数添加了两个重载签名。 第一个检查<code>myCoolFunction</code>函数是否接收一个函数(它又接收一个<code>number</code>参数)和一个<code>number</code>数组。 第二个同样是接收了一个函数,并且使用剩余参数(<code>...nums</code>)来表示之后的其它所有参数必须是<code>number</code>类型。</p>
<h4 id="连续添加属性"><a class="header" href="#连续添加属性">连续添加属性</a></h4>
<p>有些人可能会因为代码美观性而喜欢先创建一个对象然后立即添加属性:</p>
<pre><code class="language-javascript">var options = {};
options.color = "red";
options.volume = 11;
</code></pre>
<p>TypeScript会提示你不能给<code>color</code>和<code>volumn</code>赋值,因为先前指定<code>options</code>的类型为<code>{}</code>并不带有任何属性。 如果你将声明变成对象字面量的形式将不会产生错误:</p>
<pre><code class="language-typescript">let options = {
color: "red",
volume: 11
};
</code></pre>
<p>你还可以定义<code>options</code>的类型并且添加类型断言到对象字面量上。</p>
<pre><code class="language-typescript">interface Options { color: string; volume: number }
let options = {} as Options;
options.color = "red";
options.volume = 11;
</code></pre>
<p>或者,你可以将<code>options</code>指定成<code>any</code>类型,这是最简单的,但也是获益最少的。</p>
<h4 id="anyobject和"><a class="header" href="#anyobject和"><code>any</code>,<code>Object</code>,和<code>{}</code></a></h4>
<p>你可能会试图使用<code>Object</code>或<code>{}</code>来表示一个值可以具有任意属性,因为<code>Object</code>是最通用的类型。 然而在这种情况下**<code>any</code>是真正想要使用的类型**,因为它是最_灵活_的类型。</p>
<p>比如,有一个<code>Object</code>类型的东西,你将不能够在其上调用<code>toLowerCase()</code>。</p>
<p>越普通意味着更少的利用类型,但是<code>any</code>比较特殊,它是最普通的类型但是允许你在上面做任何事情。 也就是说你可以在上面调用,构造它,访问它的属性等等。 记住,当你使用<code>any</code>时,你会失去大多数TypeScript提供的错误检查和编译器支持。</p>
<p>如果你还是决定使用<code>Object</code>和<code>{}</code>,你应该选择<code>{}</code>。 虽说它们基本一样,但是从技术角度上来讲<code>{}</code>在一些深奥的情况里比<code>Object</code>更普通。</p>
<h3 id="启用严格检查"><a class="header" href="#启用严格检查">启用严格检查</a></h3>
<p>TypeScript提供了一些检查来保证安全以及帮助分析你的程序。 当你将代码转换为了TypeScript后,你可以启用这些检查来帮助你获得高度安全性。</p>
<h4 id="没有隐式的any"><a class="header" href="#没有隐式的any">没有隐式的<code>any</code></a></h4>
<p>在某些情况下TypeScript没法确定某些值的类型。 那么TypeScript会使用<code>any</code>类型代替。 这对代码转换来讲是不错,但是使用<code>any</code>意味着失去了类型安全保障,并且你得不到工具的支持。 你可以使用<code>noImplicitAny</code>选项,让TypeScript标记出发生这种情况的地方,并给出一个错误。</p>
<h4 id="严格的null与undefined检查"><a class="header" href="#严格的null与undefined检查">严格的<code>null</code>与<code>undefined</code>检查</a></h4>
<p>默认地,TypeScript把<code>null</code>和<code>undefined</code>当做属于任何类型。 这就是说,声明为<code>number</code>类型的值可以为<code>null</code>和<code>undefined</code>。 因为在JavaScript和TypeScript里,<code>null</code>和<code>undefined</code>经常会导致BUG的产生,所以TypeScript包含了<code>strictNullChecks</code>选项来帮助我们减少对这种情况的担忧。</p>
<p>当启用了<code>strictNullChecks</code>,<code>null</code>和<code>undefined</code>获得了它们自己各自的类型<code>null</code>和<code>undefined</code>。 当任何值_可能_为<code>null</code>,你可以使用联合类型。 比如,某值可能为<code>number</code>或<code>null</code>,你可以声明它的类型为<code>number | null</code>。</p>
<p>假设有一个值TypeScript认为可以为<code>null</code>或<code>undefined</code>,但是你更清楚它的类型,你可以使用<code>!</code>后缀。</p>
<pre><code class="language-typescript">declare var foo: string[] | null;
foo.length; // error - 'foo' is possibly 'null'
foo!.length; // okay - 'foo!' just has type 'string[]'
</code></pre>
<p>要当心,当你使用<code>strictNullChecks</code>,你的依赖也需要相应地启用<code>strictNullChecks</code>。</p>
<h4 id="this没有隐式的any"><a class="header" href="#this没有隐式的any"><code>this</code>没有隐式的<code>any</code></a></h4>
<p>当你在类的外部使用<code>this</code>关键字时,它会默认获得<code>any</code>类型。 比如,假设有一个<code>Point</code>类,并且我们要添加一个函数做为它的方法:</p>
<pre><code class="language-typescript">class Point {
constructor(public x, public y) {}
getDistance(p: Point) {
let dx = p.x - this.x;
let dy = p.y - this.y;
return Math.sqrt(dx ** 2 + dy ** 2);
}
}
// ...
// Reopen the interface.
interface Point {
distanceFromOrigin(point: Point): number;
}
Point.prototype.distanceFromOrigin = function(point: Point) {
return this.getDistance({ x: 0, y: 0});
}
</code></pre>
<p>这就产生了我们上面提到的错误 - 如果我们错误地拼写了<code>getDistance</code>并不会得到一个错误。 正因此,TypeScript有<code>noImplicitThis</code>选项。 当设置了它,TypeScript会产生一个错误当没有明确指定类型(或通过类型推断)的<code>this</code>被使用时。 解决的方法是在接口或函数上使用指定了类型的<code>this</code>参数:</p>
<pre><code class="language-typescript">Point.prototype.distanceFromOrigin = function(this: Point, point: Point) {
return this.getDistance({ x: 0, y: 0});
}
</code></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../../zh/tutorials/angular-2.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../../zh/handbook/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../../zh/tutorials/angular-2.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next prefetch" href="../../zh/handbook/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script>
window.playground_copyable = true;
</script>
<script src="../../elasticlunr.min.js"></script>
<script src="../../mark.min.js"></script>
<script src="../../searcher.js"></script>
<script src="../../clipboard.min.js"></script>
<script src="../../highlight.js"></script>
<script src="../../book.js"></script>
<!-- Custom JS scripts -->
</div>
</body>
</html>