如何修复 Deno 程序中 std 模块依赖的编译器错误?

How to fix compiler error for std module dependency in Deno program?

我知道有一个关于 SO 的问题有同样的错误,但那里的答案对我没有帮助:

这是完整的错误:

❯ deno 运行 --allow-all server.ts 检查文件:///Users/hagenek/repos/mock-backend/server.ts 错误:TS2339 [错误]:属性 'getIterator' 在类型 'ReadableStream' 上不存在。 return res.readable.getIterator(); ~~~~~~~~~~~ 在 https://deno.land/std@0.83.0/async/pool.ts:45:23

这是我的 server.ts 代码:

import { Application } from "./deps.ts";
import router from "./routes.ts"
const PORT = 4000;
const app = new Application();

app.use(router.routes()); // Pass our router as a middleware
app.use(router.allowedMethods()); // Allow HTTP methods on router

await app.listen({ port: PORT });
console.log(`Server running on PORT: ${PORT}`)

Routes.ts:

import { Router } from "https://deno.land/x/oak/mod.ts";
import {
    addQuote,
    getQuotes,
    getQuote,
    updateQuote,
    deleteQuote,
} from "./controllers/controller.ts";

interface ReadableStream<R> {
    getIterator(): any
}

const router = new Router(); // Create Router

    router
        .get("/api/quote", getQuotes) // Get all quotes
        .get("/api/quote/:id", getQuote) // Get one quote of quoteID: id
        .post("/api/quote", addQuote) // Add a quote
        .put("/api/quote/:id", updateQuote) // Update a quote
        .delete("/api/quote/:id", deleteQuote); // Delete a quote
    
    export default router;

Deps.ts

export {
    Application
} from "https://deno.land/x/oak/mod.ts"

Controller.ts

interface Quote {
    _id: { $oid: string };
    quote: string;
    quoteID: string;
    author: string;
}

import {MongoClient} from "https://deno.land/x/mongo@v0.22.0/mod.ts";

const URI = "mongodb://127.0.0.1:27017";

// Mongo Connection Init
const client = new MongoClient();
try {
    await client.connect(URI);
    console.log("Database successfully connected");
} catch (err) {
    console.log(err);
}

const db = client.database("quotesApp");
const quotes = db.collection<Quote>("quotes");

// DESC: ADD single quote
// METHOD: POST /api/quote
export const addQuote = async ({request, response,}: {
    request: any;
    response: any;
}) => {
    try {
        // If the request has no Body, it will return a 404
        if (!request.hasBody) {
            response.status = 400;
            response.body = {
                success: false,
                msg: "No Data",
            };
        } else {
            // Otherwise, it will try to insert
            // a quote in the DB and respond with 201
            const body = await request.body();
            const quote = await body.value;
            await quotes.insertOne(quote);
            response.status = 201;
            response.body = {
                success: true,
                data: quote,
            };
        }
    } catch (err) {
        response.body = {
            success: false,
            msg: err.toString(),
        };
    }
};

// DESC: GET single quote
// METHOD: GET /api/quote/:id
export const getQuote = async ({
                            params,
                            response,
                        }: {
    params: { id: string };
    response: any;
}) => {
    // Searches for a particular quote in the DB
    const quote = await quotes.findOne({quoteID: params.id});
    // If found, respond with the quote. If not, respond with a 404
    if (quote) {
        response.status = 200;
        response.body = {
            success: true,
            data: quote,
        };
    } else {
        response.status = 404;
        response.body = {
            success: false,
            msg: "No quote found",
        };
    }
};

// DESC: GET all Quotes
// METHOD GET /api/quote
export const getQuotes = async ({response}: { response: any }) => {
    try {
        // Find all quotes and convert them into an Array
        const allQuotes = await quotes.find({}).toArray();
        console.log(allQuotes);
        if (allQuotes) {
            response.status = 200;
            response.body = {
                success: true,
                data: allQuotes,
            };
        } else {
            response.status = 500;
            response.body = {
                success: false,
                msg: "Internal Server Error",
            };
        }
    } catch (err) {
        response.body = {
            success: false,
            msg: err.toString(),
        };
    }
};

// DESC: UPDATE single quote
// METHOD: PUT /api/quote/:id
export const updateQuote = async ({
                               params,
                               request,
                               response,
                           }: {
    params: { id: string };
    request: any;
    response: any;
}) => {
    try {
        // Search a quote in the DB and update with given values if found
        const body = await request.body();
        const inputQuote = await body.value;
        await quotes.updateOne(
            { quoteID: params.id },
            { $set: { quote: inputQuote.quote, author: inputQuote.author } }
        );
        // Respond with the Updated Quote
        const updatedQuote = await quotes.findOne({ quoteID: params.id });
        response.status = 200;
        response.body = {
            success: true,
            data: updatedQuote,
        };
    } catch (err) {
        response.body = {
            success: false,
            msg: err.toString(),
        };
    }
};


// DESC: DELETE single quote
// METHOD: DELETE /api/quote/:id
export const deleteQuote = async ({
                               params,
                               response,
                           }: {
    params: { id: string };
    request: any;
    response: any;
}) => {
    try {
        // Search for the given quote and drop it from the DB
        await quotes.deleteOne({quoteID: params.id});
        response.status = 201;
        response.body = {
            success: true,
            msg: "Product deleted",
        };
    } catch (err) {
        response.body = {
            success: false,
            msg: err.toString(),
        };
    }
};

问题

您使用的是 deno.land/x/mongo 的过时版本(v0.22.0,其依赖项也已过时且与 Deno 当前的内置类型库不一致)。

解决方法

使用与您正在使用的 Deno 版本兼容的模块版本。

在撰写此答案时,Deno 稳定版为 v1.16.3,该模块的最新版本为 v0.28.0https://deno.land/x/mongo@v0.28.0。它们似乎兼容。

说明

这是您的模块的编译器错误:

% deno cache server.ts 
Check file:///Users/deno/so-70169022/server.ts
error: TS2339 [ERROR]: Property 'getIterator' does not exist on type 'ReadableStream<R>'.
  return res.readable.getIterator();
                      ~~~~~~~~~~~
    at https://deno.land/std@0.83.0/async/pool.ts:45:23

For reference, here's the version of Deno I'm using:

% deno --version
deno 1.16.3 (release, x86_64-apple-darwin)
v8 9.7.106.5
typescript 4.4.2

您可以看到错误发生在 https://deno.land/std@0.83.0/async/pool.ts 的模块中(不幸的是,您无法通过编辑来解决问题)。请注意,它是 std 库中的一个模块(我会回来讨论这个)。

这是您的入口点的模块图:

Note: I've removed all of the lines in the output unrelated to the problematic module in order to improve readability

% deno info server.ts
local: /Users/deno/so-70169022/server.ts
type: TypeScript
dependencies: 134 unique (total 1.72MB)

file:///Users/deno/so-70169022/server.ts (334B)
└─┬ file:///Users/deno/so-70169022/routes.ts (638B)
  └─┬ file:///Users/deno/so-70169022/controllers/controller.ts (4.24KB)
    └─┬ https://deno.land/x/mongo@v0.22.0/mod.ts (113B)
      └─┬ https://deno.land/x/mongo@v0.22.0/deps.ts (783B)
        └─┬ https://deno.land/std@0.83.0/node/_crypto/pbkdf2.ts (4.18KB)
          └─┬ https://deno.land/std@0.83.0/node/buffer.ts (15.46KB)
            └─┬ https://deno.land/std@0.83.0/node/_utils.ts (5.74KB)
              └─┬ https://deno.land/std@0.83.0/async/mod.ts (202B)
                └── https://deno.land/std@0.83.0/async/pool.ts (1.58KB)

有问题的模块位于 std 库的一系列嵌套导入的底部,这些嵌套导入导致 mongo/deps.ts and mongo/mod.ts,它由 ./controllers/controller.ts 导入(这是您可以直接编辑以解决问题的第一个模块。

现在我将暂停片刻重新访问 std 个模块:

https://deno.land/std@0.116.0#releases 它是这样说的:

Standard library is currently tagged independently of Deno version. This will change once the library is stabilized.

To check compatibility of different version of standard library with Deno CLI see this list.

这意味着 std 库的每个版本只保证与特定版本的 Deno 兼容。

您程序中 mongo 模块当前使用的 std 库的版本是 v0.83.0,并且参考上面的链接兼容性 JSON 列表,你会发现它映射到 Deno v1.6.3(相当旧)。

此时,您最容易访问的选项是:

  1. 使用与 mongo 模块版本兼容的 Deno 版本(使用旧版本的 Deno 可能不是最好的主意),或者

  2. 使用与较新版本的 Deno 兼容的 mongo 模块版本(让我们先试试这个)

让我们看看mongo模块的最新版本是什么:

https://deno.land/x/mongo@v0.28.0/deps.ts 是目前的最新版本,它使用 std 库的 v0.111.0

让我们尝试更新程序中 mongo 模块的版本,看看它是否修复了编译器错误:

./controllers/controller.ts(第 8 行):

// before:
// import {MongoClient} from "https://deno.land/x/mongo@v0.22.0/mod.ts";

// after:
import {MongoClient} from "https://deno.land/x/mongo@v0.28.0/mod.ts";

现在让我们再次输入检查并缓存您的入口点:

% deno cache server.ts

这次没有编译错误!