【问题标题】:How to fix compiler error for std module dependency in Deno program?如何修复 Deno 程序中 std 模块依赖项的编译器错误?
【发布时间】:2022-01-07 03:33:40
【问题描述】:

我知道在 SO 上有一个同样错误的问题,但那里的答案对我没有帮助:deno bundle failed. Property 'getIterator' does not exist on type 'ReadableStream<R>'

这是完整的错误:

❯ deno run --allow-all server.ts 检查文件:///Users/hagenek/repos/mock-backend/server.ts 错误:TS2339 [错误]:“ReadableStream”类型上不存在属性“getIterator”。 返回 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(),
        };
    }
};

【问题讨论】:

  • 我看不到您尝试在哪里使用res.readable.getIterator()(来自您问题标题中的错误消息)。您是否还可以在./controllers/controller.ts 中包含模块的代码(以及任何相关代码,如果相关)?能够重现您的问题将有助于确定解决方案。
  • 补充了更多信息,希望对您调试有帮助。

标签: dependencies deno


【解决方案1】:

问题

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

解决方案

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

在撰写此答案时,Deno 稳定版位于 v1.16.3,该模块的最新版本是 v0.28.0:https://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

作为参考,这是我正在使用的 Deno 版本:

% 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 库中的一个模块(我会回到这个)。

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

注意:为了提高可读性,我已经删除了输出中与问题模块无关的所有行

% 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.tsmongo/mod.ts,由./controllers/controller.ts 导入(这是第一个模块您可以直接编辑以解决问题)。

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

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

标准库目前独立于 Deno 版本进行标记。一旦库稳定下来,这将改变。

要检查不同版本标准库与 Deno CLI 的兼容性,请参阅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

这次没有编译错误! ?

【讨论】:

    猜你喜欢
    • 2018-09-03
    • 2017-08-12
    • 2014-03-10
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    相关资源
    最近更新 更多