使用 Deno 编译时如何使用 lib.dom.d.ts 中的类型?

How to use types from lib.dom.d.ts when compiling with Deno?

我正在使用 Deno 编译一些 TypeScript,然后将其作为网页的一部分提供,因此它在浏览器端是 运行。我正在尝试在客户端使用 canvas 元素,为此我需要像 CanvasRenderingContext2DCanvasGradient 这样的类型,它们在 lib.dom.d.ts 中定义,但它们是不可用:Deno 编译会给出类似 TS2304 [ERROR]: Cannot find name 'CanvasRenderingContext2D'. 的错误。 (另一方面,类型 Path2D(在同一个文件中定义)不会导致问题。)

注意:我知道当代码 运行 存在于浏览器中时,类型将在 运行 时间存在,但我希望 Deno 在编译时知道它们。

我试过以某种方式包含 .d.ts 文件。我尝试过的事情:

/// <reference types="https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.dom.d.ts" />
// @deno-types="https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.dom.d.ts"

其中一些尝试根本不起作用,有些甚至显然没有被解析。看起来我不明白 Deno 如何加载类型定义,例如它从哪里加载 Path2D 类型声明。如何解决这个问题?

您需要将 Deno 配置为在 type-checking 您的程序中使用 DOM 和 ES 类型。您可以使用 Deno 配置文件中受支持的 TypeScript 编译器选项来执行此操作:

./deno.json:

{
  "compilerOptions": {
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ]
  }
}

这指示编译器该程序不会在 Deno 中 运行,而是在具有这些环境全局类型的 browser-like 环境中。

这是一个示例源文件:

./main.ts

import {assertExists} from 'https://deno.land/std@0.126.0/testing/asserts.ts';

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
assertExists(ctx);

当您从其他 TypeScript 模块导入到像这样的模块时

  • 将由 Deno 编译,并且
  • 注定要在browser-like环境下执行

那么你必须打包结果,因为浏览器无法将 TypeScript 源模块作为导入处理:

deno bundle --config deno.json main.ts main.js

结果 JavaScript 如下所示:

// deno-fmt-ignore-file
// deno-lint-ignore-file
// This code was bundled using `deno bundle` and it's not recommended to edit it manually

const { Deno  } = globalThis;
typeof Deno?.noColor === "boolean" ? Deno.noColor : true;
new RegExp([
    "[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)",
    "(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-ntqry=><~]))", 
].join("|"), "g");
var DiffType;
(function(DiffType1) {
    DiffType1["removed"] = "removed";
    DiffType1["common"] = "common";
    DiffType1["added"] = "added";
})(DiffType || (DiffType = {}));
class AssertionError extends Error {
    name = "AssertionError";
    constructor(message){
        super(message);
    }
}
function assertExists(actual, msg) {
    if (actual === undefined || actual === null) {
        if (!msg) {
            msg = `actual: "${actual}" expected to not be null or undefined`;
        }
        throw new AssertionError(msg);
    }
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
assertExists(ctx);

在程序编译中使用位于 https://deno.land/std@0.126.0/testing/asserts.ts 的模块是安全的,因为在尝试使用其任何 API 之前,它会运行 Deno 命名空间 feature-detection。任何不这样做的模块都会导致运行时错误。