使用 Deno 编译时如何使用 lib.dom.d.ts 中的类型?
How to use types from lib.dom.d.ts when compiling with Deno?
我正在使用 Deno 编译一些 TypeScript,然后将其作为网页的一部分提供,因此它在浏览器端是 运行。我正在尝试在客户端使用 canvas 元素,为此我需要像 CanvasRenderingContext2D
或 CanvasGradient
这样的类型,它们在 lib.dom.d.ts 中定义,但它们是不可用:Deno 编译会给出类似 TS2304 [ERROR]: Cannot find name 'CanvasRenderingContext2D'.
的错误。 (另一方面,类型 Path2D
(在同一个文件中定义)不会导致问题。)
注意:我知道当代码 运行 存在于浏览器中时,类型将在 运行 时间存在,但我希望 Deno 在编译时知道它们。
我试过以某种方式包含 .d.ts 文件。我尝试过的事情:
- 在编译器选项中指定
"libs": ["deno.window", "esnext"]
等(在 deno.json 中)。
- 像这样导入类型:
/// <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。任何不这样做的模块都会导致运行时错误。
我正在使用 Deno 编译一些 TypeScript,然后将其作为网页的一部分提供,因此它在浏览器端是 运行。我正在尝试在客户端使用 canvas 元素,为此我需要像 CanvasRenderingContext2D
或 CanvasGradient
这样的类型,它们在 lib.dom.d.ts 中定义,但它们是不可用:Deno 编译会给出类似 TS2304 [ERROR]: Cannot find name 'CanvasRenderingContext2D'.
的错误。 (另一方面,类型 Path2D
(在同一个文件中定义)不会导致问题。)
注意:我知道当代码 运行 存在于浏览器中时,类型将在 运行 时间存在,但我希望 Deno 在编译时知道它们。
我试过以某种方式包含 .d.ts 文件。我尝试过的事情:
- 在编译器选项中指定
"libs": ["deno.window", "esnext"]
等(在 deno.json 中)。 - 像这样导入类型:
/// <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。任何不这样做的模块都会导致运行时错误。