本页内容

在 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.jsondeno.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 自带的类型库是 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 Workers 的更多信息,请查看 类型检查 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 Workers 的主要库。与 "dom" 一样,它会与 "deno.window""deno.worker" 冲突,因此考虑仅使用 "deno.ns" 来公开 Deno 特定的 API。
  • "webworker.importscripts" - 公开 Web Worker 中 importScripts() API 的库。
  • "webworker.iterable" - 在 Web Worker 中为对象添加可迭代对象的库。现代浏览器支持此功能。

针对 Deno 和浏览器 跳转到标题

一个常见的用例是编写在 Deno 和浏览器中都能工作的代码:使用条件检查来确定代码执行的环境,然后再使用任何仅限于其中一个环境的 API。如果是这种情况,compilerOptions 的常见配置如下所示

{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
  }
}

这应该允许 Deno 正确地对大多数代码进行类型检查。

如果你希望在 Deno 中使用 --unstable 标志运行代码,那么你将需要将该库也添加到混合中

{
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "dom",
      "dom.iterable",
      "dom.asynciterable",
      "deno.ns",
      "deno.unstable"
    ]
  }
}

通常,当你使用 TypeScript 中的 "lib" 选项时,你还需要包含一个 "es" 库。在 "deno.ns""deno.unstable" 的情况下,它们会在你引入它们时自动包含 "esnext"

这样做最大的“危险”是类型检查会变得非常宽松,并且没有办法验证你是否在代码中进行了充分有效的特性检测,这可能会导致原本微不足道的错误变成运行时错误。

使用 "types" 属性 跳转到标题

"compilerOptions" 中的 "types" 属性可用于指定在类型检查程序时要包含的任意类型定义。有关此内容的更多信息,请参阅 使用环境或全局类型