在 Deno 中配置 TypeScript
TypeScript 带有许多不同的配置选项,但 Deno 努力使 TypeScript 与 Deno 的使用变得容易。许多不同的选项会阻碍这一目标。为了简化操作,Deno 配置 TypeScript 使其“正常工作”,无需额外配置。
也就是说,Deno 支持使用 TypeScript 配置文件。要在 Deno 中使用 TypeScript 配置文件,您可以在命令行中提供路径,或使用默认路径。例如
> deno run --config ./deno.json main.ts
⚠️ 但是请注意,如果您正在创建需要配置文件的库,那么如果您将模块作为 TypeScript 分发,所有使用您模块的用户也将需要该配置文件。此外,您在配置文件中进行的设置可能会导致其他 TypeScript 模块不兼容。老实说,最好使用 Deno 默认设置,并认真考虑是否使用配置文件。
⚠️ Deno v1.14 开始支持更通用的配置文件,不再局限于指定 TypeScript 编译器设置。使用
tsconfig.json作为文件名仍然有效,但我们建议使用deno.json或deno.jsonc,因为计划在即将发布的版本中自动查找此文件。
Deno 如何使用配置文件
Deno 不会像 tsc 那样处理 TypeScript 配置文件,因为 TypeScript 配置文件中有很多部分在 Deno 上下文中毫无意义,或者如果应用它们会导致 Deno 无法正常运行。
Deno 只会查看配置文件中的 compilerOptions 部分,即使这样,它也只考虑某些编译器选项,其余选项将被忽略。
以下是可以更改的编译器选项、它们在 Deno 中的默认值以及有关该选项的其他说明
| 选项 | 默认值 | 说明 |
|---|---|---|
allowJs | true | 这几乎不需要更改 |
allowUnreachableCode | false | |
allowUnusedLabels | false | |
checkJs | false | 如果为 true,则会导致 TypeScript 对 JavaScript 进行类型检查 |
jsx | "react" | |
jsxFactory | "React.createElement" | |
jsxFragmentFactory | "React.Fragment" | |
keyofStringsOnly | false | |
lib | [ "deno.window" ] | 此选项的默认值根据 Deno 中的其他设置而有所不同。如果提供了此选项,它将覆盖默认值。有关更多信息,请参见下文。 |
noErrorTruncation | false | |
noFallthroughCasesInSwitch | false | |
noImplicitAny | true | |
noImplicitReturns | false | |
noImplicitThis | true | |
noImplicitUseStrict | true | |
noStrictGenericChecks | false | |
noUnusedLocals | false | |
noUnusedParameters | false | |
noUncheckedIndexedAccess | false | |
reactNamespace | React | |
strict | true | |
strictBindCallApply | true | |
strictFunctionTypes | true | |
strictPropertyInitialization | true | |
strictNullChecks | true | |
suppressExcessPropertyErrors | false | |
suppressImplicitAnyIndexErrors | false | |
useUnknownInCatchVariables | false |
有关编译器选项的完整列表及其对 TypeScript 的影响,请参阅 TypeScript 手册。
隐式 tsconfig.json 的样子
无法让tsc像Deno一样运行。同样,也很难让TypeScript语言服务像Deno一样运行。这就是我们直接在Deno中构建语言服务的原因。话虽如此,理解其中的含义还是很有用的。
如果你要为Deno编写一个tsconfig.json,它看起来会像这样
{
"compilerOptions": {
"allowJs": true,
"esModuleInterop": true,
"experimentalDecorators": false,
"inlineSourceMap": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["deno.window"],
"module": "esnext",
"moduleDetection": "force",
"strict": true,
"target": "esnext",
"useDefineForClassFields": true
}
}
你不能直接将这段代码复制粘贴到配置文件中并使其生效,特别是因为Deno内置了自定义的类型库,这些库是提供给TypeScript编译器的。可以通过在命令行中运行deno types并将输出管道到一个文件,并将该文件包含在程序文件中,删除"lib"选项,并将"noLib"选项设置为true来模拟这种行为。
如果你使用--unstable标志,Deno会将"lib"选项更改为[ "deno.window", "deno.unstable" ]。如果你尝试加载一个worker,它将使用"deno.worker"而不是"deno.window"进行类型检查。有关此方面的更多信息,请参阅类型检查Web Workers。
使用"lib"属性
Deno内置了一些其他平台(如tsc)中不存在的库。这使得Deno能够正确地检查为Deno编写的代码。但在某些情况下,这种自动行为会导致挑战,例如编写旨在也在浏览器中运行的代码。在这些情况下,可以使用compilerOptions中的"lib"属性来修改Deno在类型检查代码时的行为。
对用户来说,内置库中最重要的是
"deno.ns"- 这包括所有自定义的Deno全局命名空间API以及Deno对import.meta的扩展。这通常不会与其他库或全局类型发生冲突。"deno.unstable"- 这包括添加的不稳定Deno全局命名空间API。"deno.window"- 这是检查Deno主运行时脚本时使用的“默认”库。它包括"deno.ns"以及内置于Deno的扩展的其他类型库。该库将与"dom"和"dom.iterable"等标准TypeScript库发生冲突。"deno.worker"- 这是检查Deno Web Worker脚本时使用的库。有关Web Worker的更多信息,请查看类型检查Web Workers。"dom.asynciterable"- TypeScript 目前不包含 Deno(以及多个浏览器)实现的 DOM 异步可迭代对象,因此我们自己实现了它,直到它在 TypeScript 中可用。
这些是 Deno 不使用的常用库,但在编写旨在在其他运行时中也工作的代码时很有用。
"dom"- 与 TypeScript 一起提供的主要的浏览器全局库。类型定义在许多方面与"deno.window"冲突,因此如果使用"dom",则考虑仅使用"deno.ns"来公开 Deno 特定的 API。"dom.iterable"- 浏览器全局库的可迭代扩展。"scripthost"- Microsoft Windows 脚本宿主库。"webworker"- 浏览器中 Web 工作者的主要库。与"dom"一样,这将与"deno.window"或"deno.worker"冲突,因此考虑仅使用"deno.ns"来公开 Deno 特定的 API。"webworker.importscripts"- 公开 Web 工作者中importScripts()API 的库。"webworker.iterable"- 在 Web 工作者中向对象添加可迭代对象的库。现代浏览器支持此功能。
针对 Deno 和浏览器
一个常见的用例是编写在 Deno 和浏览器中都能工作的代码:使用条件检查来确定代码执行的环境,然后再使用任何仅限于其中一个环境的 API。如果是这种情况,compilerOptions 的常见配置如下所示
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
}
}
这应该允许 Deno 正确地对大多数代码进行类型检查。
如果您希望使用 --unstable 标志在 Deno 中运行代码,那么您还需要将该库添加到混合中
{
"compilerOptions": {
"target": "esnext",
"lib": [
"dom",
"dom.iterable",
"dom.asynciterable",
"deno.ns",
"deno.unstable"
]
}
}
通常,当您在 TypeScript 中使用 "lib" 选项时,您还需要包含一个 "es" 库。在 "deno.ns" 和 "deno.unstable" 的情况下,它们在您引入它们时会自动包含 "esnext"。
这样做最大的 "危险" 是类型检查明显更宽松,并且无法验证您是否在代码中进行了充分有效的特性检测,这可能会导致原本微不足道的错误变成运行时错误。
使用 "types" 属性
在 "compilerOptions" 中的 "types" 属性可用于指定在类型检查程序时要包含的任意类型定义。有关此内容的更多信息,请参见 使用环境或全局类型。