本页内容

Deno 中的 TypeScript 概述

Deno 的优势之一是它将 TypeScript 视为一等公民语言,就像 JavaScript 或 WebAssembly 一样,在 Deno 中运行代码时。这意味着您可以在 Deno 中运行或导入 TypeScript,而无需安装任何其他内容,除了 Deno CLI。

等等,Deno 真的运行 TypeScript 吗?您可能会问自己。嗯,这取决于你对“运行”的定义。有人可能会说,在浏览器中,您实际上并没有运行 JavaScript。浏览器中的 JavaScript 引擎将 JavaScript 转换为一系列操作码,然后在沙箱中执行这些操作码。因此它将 JavaScript 转换为类似于汇编的东西。即使 WebAssembly 也经过类似的转换,因为 WebAssembly 是与架构无关的,而它需要被转换为特定平台架构所需的机器特定操作码。因此,当我们说 TypeScript 是 Deno 中的一等公民语言时,我们的意思是,我们试图使 TypeScript 的编写和运行体验与 JavaScript 和 WebAssembly 一样简单直观。

在幕后,我们使用 Rust 和 JavaScript 中的一系列技术来提供这种体验。

它是如何工作的? 跳转到标题

在高层次上,Deno 将 TypeScript(以及 TSX 和 JSX)转换为 JavaScript。它通过结合 TypeScript 编译器(我们将其构建到 Deno 中)和一个名为 swc 的 Rust 库来实现。当代码经过类型检查和转换后,它将存储在缓存中,准备在下一次运行时使用,无需再次将其从源代码转换为 JavaScript。

您可以通过运行 deno info 来查看此缓存位置。

> deno info
DENO_DIR location: "/path/to/cache/deno"
Remote modules cache: "/path/to/cache/deno/deps"
TypeScript compiler cache: "/path/to/cache/deno/gen"

如果您查看该缓存,您将看到一个目录结构,它模仿源目录结构,以及单独的 .js.meta 文件(也可能包含 .map 文件)。.js 文件是转换后的源文件,而 .meta 文件包含我们想要缓存的有关该文件元数据,目前包含源模块的哈希,这有助于我们管理缓存失效。您可能还会看到一个 .buildinfo 文件,它是一个 TypeScript 编译器增量构建信息文件,我们将其缓存以帮助加快类型检查速度。

类型检查 跳转到标题

TypeScript 的主要优势之一是您可以使代码更类型安全,因此,在语法上有效的 JavaScript 将成为带有“不安全”警告的 TypeScript。

您可以使用以下命令对代码进行类型检查(而不执行它)

deno check module.ts
# or also type check remote modules and npm packages
deno check --all module.ts

类型检查可能需要大量时间,尤其是在您正在处理一个代码库,并且您正在进行大量更改的情况下。我们已经尝试优化类型检查,但它仍然需要付出代价。因此,默认情况下,TypeScript 模块在执行之前不会进行类型检查。

deno run module.ts

当使用上面的命令时,Deno 只会在执行之前转译模块,忽略任何潜在的类型相关问题。为了在执行发生之前对模块进行类型检查,必须将 --check 参数与 deno run 一起使用。

deno run --check module.ts
# or also type check remote modules and npm packages
deno run --check=all module.ts

虽然 tsc 将(默认情况下)在遇到诊断(类型检查)问题时仍然发出 JavaScript,但 Deno 目前将其视为终止。当使用 deno run 以及 --check 参数时,类型相关的诊断将阻止程序运行:它将在这些警告上停止,并在执行代码之前退出进程。

为了避免这种情况,您需要解决问题,使用 // @ts-ignore// @ts-expect-error 标记,或者完全跳过类型检查。

您可以了解更多关于类型检查参数的信息 这里

确定文件类型 跳转到标题

由于 Deno 支持 JavaScript、TypeScript、JSX、TSX 模块,因此 Deno 必须决定如何处理这些类型的文件。对于本地模块,Deno 根据扩展名来确定。当本地文件没有扩展名时,它被认为是 JavaScript。可以使用 --ext 参数覆盖模块类型。这在模块没有文件扩展名时很有用,例如,因为它嵌入在另一个文件中。

对于远程模块,使用媒体类型(mime 类型)来确定模块类型,其中模块的路径用于帮助影响文件类型,当文件类型不明确时。

例如,.d.ts 文件和 .ts 文件在 TypeScript 中具有不同的语义,并且在 Deno 中需要以不同的方式处理。虽然我们希望将 .ts 文件转换为 JavaScript,但 .d.ts 文件不包含任何“可运行”代码,它只是描述类型(通常是“普通”JavaScript)。因此,当我们获取远程模块时,.ts..d.ts 文件的媒体类型看起来相同。因此,我们查看路径,如果我们看到以 .d.ts 结尾的路径,我们将它视为仅类型定义文件,而不是“可运行”TypeScript。

支持的媒体类型 跳转到标题

下表列出了 Deno 在识别远程模块文件类型时支持的媒体类型

媒体类型 文件处理方式
application/typescript TypeScript(受路径扩展名影响)
text/typescript TypeScript(受路径扩展名影响)
video/vnd.dlna.mpeg-tts TypeScript(受路径扩展名影响)
video/mp2t TypeScript(受路径扩展名影响)
application/x-typescript TypeScript(受路径扩展名影响)
application/javascript JavaScript(受路径扩展名影响)
text/javascript JavaScript(受路径扩展名影响)
application/ecmascript JavaScript(受路径扩展名影响)
text/ecmascript JavaScript(受路径扩展名影响)
application/x-javascript JavaScript(受路径扩展名影响)
application/node JavaScript(受路径扩展名影响)
text/jsx JSX
text/tsx TSX
text/plain 尝试确定路径扩展名,否则未知
application/octet-stream 尝试确定路径扩展名,否则未知

默认情况下严格 跳转到标题

Deno 默认情况下以严格模式对 TypeScript 进行类型检查,TypeScript 核心团队建议严格模式作为合理的默认值。此模式通常启用 TypeScript 的功能,这些功能可能应该从一开始就存在,但随着 TypeScript 的不断发展,对于现有代码来说将是重大更改。

混合 JavaScript 和 TypeScript 跳转到标题

默认情况下,Deno 不会对 JavaScript 进行类型检查。这可以更改,并在 在 Deno 中配置 TypeScript 中进一步讨论。Deno 支持 JavaScript 导入 TypeScript 和 TypeScript 导入 JavaScript,在复杂场景中。

但需要注意的是,在对 TypeScript 进行类型检查时,Deno 默认情况下会“读取”所有 JavaScript,以便能够评估它可能对 TypeScript 类型的影响。类型检查器将尽力弄清楚您导入到 TypeScript 中的 JavaScript 的类型,包括读取任何 JSDoc 注释。这方面的详细信息在 类型和类型声明 部分中详细讨论。

类型解析 跳转到标题

Deno 的核心设计原则之一是避免非标准模块解析,这也适用于类型解析。如果您想使用具有类型定义的 JavaScript(例如 .d.ts 文件),您必须明确告诉 Deno 关于这一点。如何实现这一点的详细信息在 类型和类型声明 部分中介绍。