Skip to content

Commit 871f94a

Browse files
Merge pull request #1304 from Kingwl/project_options
(zh) Add project options
2 parents f14b88f + addb2a7 commit 871f94a

21 files changed

+890
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
display: "工程选项"
3+
---
4+
5+
这些设置将用于指定你的工程的运行时配置,你希望 JavaScript 怎样被生成和生成在哪里,以及你希望与现有 JavaScript 代码的集成程度。
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
display: "允许 JS"
3+
oneline: "允许你的程序包含 JS 文件。使用 checkJS 来检查在这些文件中的错误。"
4+
---
5+
6+
允许 JavaScript 文件在你的工程中被引入,而不是仅仅允许 `.ts``.tsx` 文件。例如这个 JS 文件:
7+
8+
```js twoslash
9+
// @filename: card.js
10+
export const defaultCardDeck = "Heart";
11+
```
12+
13+
当你引入到一个 TypeScript 文件时将会抛出一个错误:
14+
15+
```ts twoslash
16+
// @errors: 2307
17+
// @filename: card.js
18+
module.exports.defaultCardDeck = "Heart";
19+
// ---cut---
20+
// @filename: index.ts
21+
import { defaultCardDeck } from "./card";
22+
23+
console.log(defaultCardDeck);
24+
```
25+
26+
当启用 `allowJs` 后它将被正常引入:
27+
28+
```ts twoslash
29+
// @filename: card.js
30+
module.exports.defaultCardDeck = "Heart";
31+
// ---cut---
32+
// @allowJs
33+
// @filename: index.ts
34+
import { defaultCardDeck } from "./card";
35+
36+
console.log(defaultCardDeck);
37+
```
38+
39+
这个选项是一种可以允许 `.ts``.tsx` 与现有的 JavaScript 文件共存的方式。可以用于逐步将 TypeScript 文件逐步添加到 JS 工程中。
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
display: "检查 JS"
3+
oneline: "在经过类型检查的 JavaScript 中报告错误。"
4+
---
5+
6+
`allowJs` 配合使用,当 `checkJs` 被启用时,JavaScript 文件中会报告错误。也就是相当于在项目中所有 JavaScript 文件顶部包含 `// @ts-check`
7+
8+
例如,根据 TypeScript 自带的 `parseFloat` 类型定义,这是不正确的 JavaScript:
9+
10+
```js
11+
// parseFloat 仅接受一个字符串作为参数
12+
module.exports.pi = parseFloat(3.124);
13+
```
14+
15+
当引入到一个 TypeScript 模块:
16+
17+
```ts twoslash
18+
// @allowJs
19+
// @filename: constants.js
20+
module.exports.pi = parseFloat(3.124);
21+
22+
// @filename: index.ts
23+
import { pi } from "./constants";
24+
console.log(pi);
25+
```
26+
27+
你将不会得到任何错误。但是如果你开启了 `checkJs` 选项,那么你可以从 JavaScript 文件中得到错误信息。
28+
29+
```ts twoslash
30+
// @errors: 2345
31+
// @allowjs: true
32+
// @checkjs: true
33+
// @filename: constants.js
34+
module.exports.pi = parseFloat(3.124);
35+
36+
// @filename: index.ts
37+
import { pi } from "./constants";
38+
console.log(pi);
39+
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
display: "组合"
3+
oneline: "启用约束以使工程可以引用其他工程来用于构建。"
4+
---
5+
6+
`composite` 选项会强制执行某些约束,使得构建工具(包括 在 `--build` 模式下的 TypeScript 本身)可以快速确定一个工程是否已经建立。
7+
8+
当此设置开启时:
9+
10+
- 如果没有明确指定 `rootDir`,则默认为包含 `tsconfig.json` 文件的目录。
11+
12+
- 所有实现的文件必须由 `include` 来匹配,或在 `files` 数组中指定。如果违反了这一约束,`tsc` 将告诉你哪些文件没有被指定。
13+
14+
- `declaration` 默认为 `true`
15+
16+
你可以在[手册](https://www.typescriptlang.org/docs/handbook/project-references.html)中找到关于 TypeScript 工程的文档。
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
display: "声明"
3+
oneline: "为你工程中的 TypeScript 以及 JavaScript 文件生成 .d.ts 文件。"
4+
---
5+
6+
为你工程中的每个 TypeScript 或 JavaScript 文件生成 `.d.ts` 文件。
7+
这些 `.d.ts` 文件是描述模块外部 API 的类型定义文件。
8+
像 TypeScript 这样的哦你根据可以通过 `.d.ts` 文件为非类型化的代码提供 intellisense 和精确的类型。
9+
10+
`declaration` 设置为 `true` 时,用编译器执行下面的 TypeScript 代码:
11+
12+
```ts twoslash
13+
export let helloWorld = "hi";
14+
```
15+
16+
将会生成如下这样的 `index.js` 文件:
17+
18+
```ts twoslash
19+
// @showEmit
20+
export let helloWorld = "hi";
21+
```
22+
23+
以及一个相应的 `helloWorld.d.ts`
24+
25+
```ts twoslash
26+
// @showEmittedFile: index.d.ts
27+
// @showEmit
28+
// @declaration
29+
export let helloWorld = "hi";
30+
```
31+
32+
当使用 `.d.ts` 文件处理 JavaScript 文件时,你可能需要使用 [`emitDeclarationOnly`](#emitDeclarationOnly)[`outDir`](#outDir) 来确保 JavaScript 文件不会被覆盖。
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
display: "迭代器降级"
3+
oneline: "为迭代器对象生成更符合要求但更复杂的 JavaScript。"
4+
---
5+
6+
‘降级’ 是 TypeScript 的术语,指用于转换到旧版本的 JavaScript。
7+
这个选项是为了在旧版 Javascript 运行时上更准确的实现现代 JavaScript 迭代器的概念。
8+
9+
ECMAScript 6 增加了几个新的迭代器原语:`for / of` 循环(`for (el of arr)`),数组展开(`[a, ...b]`),参数展开(`fn(...args)`)和 `Symbol.iterator`
10+
11+
如果 `Symbol.iterator` 存在的话,`--downlevelIteration` 将允许在 ES5 环境更准确的使用这些迭代原语。
12+
13+
#### 例:`for / of` 的效果
14+
15+
对于 TypeScript 代码:
16+
17+
```ts twoslash
18+
const str = "Hello!";
19+
for (const s of str) {
20+
console.log(s);
21+
}
22+
```
23+
24+
如果没有启用 `downlevelIteration``for / of` 循环将被降级为传统的 `for` 循环:
25+
26+
```ts twoslash
27+
// @target: ES5
28+
// @showEmit
29+
const str = "Hello!";
30+
for (const s of str) {
31+
console.log(s);
32+
}
33+
```
34+
35+
这通常是人们所期望的,但是它并不是 100% 符合 ECMAScript 迭代器协议。
36+
某些字符串,例如 emoji (😜),其 `.length` 为 2(甚至更多),但在 `for-of` 循环中应只有一次迭代。
37+
可以在 [Jonathan New 的这篇文章中](https://blog.jonnew.com/posts/poo-dot-length-equals-two) 找到更详细的解释。
38+
39+
`downlevelIteration` 启用时,TypeScript 将会使用辅助函数来检查 `Symbol.iterator` 的实现(无论是原生实现还是polyfill)。
40+
如果没有实现,则将会回退到基于索引的迭代。
41+
42+
```ts twoslash
43+
// @target: ES5
44+
// @downlevelIteration
45+
// @showEmit
46+
const str = "Hello!";
47+
for (const s of str) {
48+
console.log(s);
49+
}
50+
```
51+
52+
你也可以通过 [`importHelpers`](#importHelpers) 来使用 [tslib](https://www.npmjs.com/package/tslib) 以减少被内联的 JavaScript 的数量:
53+
54+
```ts twoslash
55+
// @target: ES5
56+
// @downlevelIteration
57+
// @importHelpers
58+
// @showEmit
59+
const str = "Hello!";
60+
for (const s of str) {
61+
console.log(s);
62+
}
63+
```
64+
65+
**注:** 如果在运行时不存在 `Symbol.iterator`,启用 `downlevelIteration` 将不会提高合规性。
66+
67+
#### 例:数组展开的效果
68+
69+
这是一个数组展开:
70+
71+
```js
72+
// 构建一个新的数组,其元素首先为 1,然后是 arr2 的元素。
73+
const arr = [1, ...arr2];
74+
```
75+
根据描述,听起来很容易降级到 ES5:
76+
77+
```js
78+
// The same, right?
79+
const arr = [1].concat(arr2);
80+
```
81+
82+
但是在某些罕见的情况下会明显不同。例如如果数组中有一个“洞”,缺失的索引在展开时将创建一个 _自己的_ 属性,但若使用 `concat` 则不会:
83+
84+
```js
85+
// 构建一个元素 `1` 不存在的数组
86+
let missing = [0, , 1];
87+
let spreaded = [...missing];
88+
let concated = [].concat(missing);
89+
90+
// true
91+
"1" in spreaded;
92+
// false
93+
"1" in concated;
94+
```
95+
96+
就像 `for / of` 一样,`downlevelIteration` 将使用 `Symbol.iterator`(如果存在的话)来更准确的模拟 ES6 的行为。
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
display: "导入辅助"
3+
oneline: "允许每个项目从 tslib 中导入一次辅助函数,而不是在每个文件中都包含他们。"
4+
---
5+
6+
对于某些降级行为,TypeScript 使用一些辅助代码来进行操作。例如继承类,展开数组或对象,以及异步操作。
7+
默认情况下,这些辅助代码被插入到使用它们的文件中。
8+
如果在许多不同的模块中使用相同的辅助代码,则可能会导致代码重复。
9+
10+
如果启用了 `importHelpers` 选项,这些辅助函数将从 [tslib](https://www.npmjs.com/package/tslib) 中被导入。
11+
你需要确保 `tslib` 模块在运行时可以被导入。
12+
这只影响模块,全局脚本文件不会尝试导入模块。
13+
14+
例如,对于如下 TypeScript 代码:
15+
16+
```ts
17+
export function fn(arr: number[]) {
18+
const arr2 = [1, ...arr];
19+
}
20+
```
21+
22+
开启 [`downlevelIteration`](#downlevelIteration) 并且 `importHelpers` 仍为 `false`
23+
24+
```ts twoslash
25+
// @showEmit
26+
// @target: ES5
27+
// @downleveliteration
28+
export function fn(arr: number[]) {
29+
const arr2 = [1, ...arr];
30+
}
31+
```
32+
33+
同时开始 [`downlevelIteration`](#downlevelIteration)`importHelpers`
34+
35+
```ts twoslash
36+
// @showEmit
37+
// @target: ES5
38+
// @downleveliteration
39+
// @importhelpers
40+
// @noErrors
41+
export function fn(arr: number[]) {
42+
const arr2 = [1, ...arr];
43+
}
44+
```
45+
46+
当你提供了自行实现的这些函数时,你可以使用 [`noEmitHelpers`](#noEmitHelpers)
47+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
display: "增量"
3+
oneline: "为支持增量编译工程,保存 .tsbuildinfo 文件"
4+
---
5+
6+
使 TypeScript 将上次编译的工程图信息保存到磁盘上的文件中。这将会在您编译输出的同一文件夹中创建一系列 `.tsbuildinfo` 文件。
7+
它们不会再运行时被您的 JavaScript 使用,并且可以被安全的删除。
8+
你可以在 [3.4 发布日志](/docs/handbook/release-notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental-flag) 中获取更多关于该选项的内容。
9+
10+
可以使用 [`tsBuildInfoFile`](#tsBuildInfoFile) 来控制 `.tsbuildinfo` 文件被编译到哪个文件夹。
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
display: "孤立模块"
3+
oneline: "确保每个文件都可以不依赖于其他导入而被安全转译。"
4+
---
5+
6+
虽然你可以使用 TypeScript 来从 TypeScript 中生成 JavaScript 代码,但是使用其他转译器例如 [Babel](https://babeljs.io) 也很常见。
7+
但其他转译器一次只能在一个文件上操作,这意味着它们不能进行基于完全理解类型系统后的代码转译。
8+
这个限制也同样适用于被一些构建工具使用的 TypeScript 的 `ts.transpileModule` 接口。
9+
10+
这些限制可能会导致一些 TypeScript 特性的运行时问题,例如 `const enum``namespace`
11+
设置 `isolatedModules` 选项后,TypeScript 将会在当你写的某些代码不能被单文件转译的过程正确处理时警告你。
12+
13+
它不会改变你代码的行为,也不会影响 TypeScript 的检查和代码生成过程。
14+
15+
一些当 `isolatedModules` 被启用时不工作的例子:
16+
17+
#### 导出非值标识符
18+
19+
在 TypeScript 中,你可以引入一个 _类型_,然后再将其导出:
20+
21+
```ts twoslash
22+
// @noErrors
23+
import { someType, someFunction } from "someModule";
24+
25+
someFunction();
26+
27+
export { someType, someFunction };
28+
```
29+
30+
由于 `someType` 并没有值,所以生成的 `export` 将不会导出它(否则将导致 JavaScript 运行时的错误):
31+
32+
```js
33+
export { someFunction };
34+
```
35+
36+
单文件转译器并不知道 `someType` 是否会产生一个值,所以导出一个只指向类型的名称会是一个错误。
37+
38+
#### 非模块文件
39+
40+
如果设置了 `isolatedModules`,则所有的实现文件必须是 _模块_ (也就是它有某种形式的 `import`/`export`)。如果任意文件不是模块就会发生错误:
41+
42+
```ts twoslash
43+
// @errors: 1208
44+
// @isolatedModules
45+
function fn() {}
46+
```
47+
48+
此限制不适用于 `.d.ts` 文件
49+
50+
#### 指向 `const enum` 成员
51+
52+
在 TypeScript 中,当你引用一个 `const enum` 的成员时,该引用在生成的 JavaScript 中将会被其实际值所代替。这会将这样的 TypeScript 代码:
53+
54+
```ts twoslash
55+
declare const enum Numbers {
56+
Zero = 0,
57+
One = 1,
58+
}
59+
console.log(Numbers.Zero + Numbers.One);
60+
```
61+
62+
转换为这样的 JavaScript:
63+
64+
```ts twoslash
65+
// @showEmit
66+
// @removeComments
67+
declare const enum Numbers {
68+
Zero = 0,
69+
One = 1,
70+
}
71+
console.log(Numbers.Zero + Numbers.One);
72+
```
73+
74+
在不知道这些成员值的情况下,其他转译器不能替换对 `Numbers` 的引用。如果无视的话则会导致运行时错误(运行时没有 `Numbers`) 对象。
75+
正因如此,当启用 `isolatedModules` 时,引用环境中的 `const enum` 成员将会是一个错误。

0 commit comments

Comments
 (0)