簡體   English   中英

使用 typescript 在節點項目中導入節點獲取

[英]Importing node-fetch in node project with typescript

如何將node-fetch package 導入我使用typescript的節點項目。 我嘗試了很多方法……現在我在:

const fetch = (...args) =>
    import("node-fetch").then(({ default: fetch }) => fetch(...args));

但是我有兩個錯誤:

Cannot redeclare block-scoped variable 'fetch'.

A spread argument must either have a tuple type or be passed to a rest parameter.

當我將const fetch =更改為const fetchIt =之類的任何其他名稱時,它修復了第一個錯誤但是......我真的必須改變它嗎? 如何在可以使用fetch()方法的情況下以正常方式導入node-fetch package? 在 React 中我只是做

import fetch from 'node-fetch';

一切正常......為什么在node項目中如此困難?

如果您與全局fetch發生沖突,這表明您在tsconfig.json中啟用了DOM庫,例如:

{
  "compilerOptions": {
    "lib": ["es2021", "dom"]
  }
}

我建議刪除它。 對於 NodeJS 項目,根據 NodeJS 版本查看建議的tsconfig.json設置的答案

在此之后,您將能夠按照您在問題中所寫的方式導入fetch並將其分配給名為fetch的變量,而不會出現名稱沖突:

import fetch from 'node-fetch';

替代解決方案:如果您需要使用以瀏覽器為重點並需要全局提取的第 3 方庫,請查看isomorphic-fetch模塊,該模塊將fetch添加為全局 function。

您將需要導入一次,以便fetch在全球范圍內可用:

import 'isomorphic-fetch';

在這種情況下,您的tsconfig.json的編譯器選項應該包含dom庫。

2022-02-04 更新

較新的 NodeJS 版本現在提供本機fetch API,因此以后不再需要上述內容。 有關更多信息,請參見此處此處

更新:

我下面的原始帖子都是真的。 然而,我已經能夠讓它工作,而無需切換到 ESM 模塊。 這是我的代碼中的工作內容(基於以下帖子中的第三個代碼片段: https://github.com/node-fetch/node-fetch/issues/1279#issuecomment-915063354

// eslint-disable-next-line no-new-func
const importDynamic = new Function('modulePath', 'return import(modulePath)');

const fetch = async (...args:any[]) => {
  const module = await importDynamic('node-fetch');
  return module.default(...args);
};

原帖:

Cannot redeclare block-scoped variable 'fetch'錯誤是因為您要聲明一個const fetch變量,然后在該行后面的then()回調中重用名稱“ fetch ”作為對象解構參數。

因此,將行更改為如下所示可以清除該錯誤:

const fetch = (...args) => import("node-fetch").then(module => module.default(...args));

至於另一個錯誤( A spread argument must either have a tuple type or be passed to a rest parameter. ),解決此問題的一種可能方法是實際為fetch()調用導入正確的參數類型,然后替換為上面的代碼片段視情況而定,如下所示:

import { RequestInfo, RequestInit } from 'node-fetch';
const fetch = (url:RequestInfo, init?:RequestInit) => import('node-fetch').then(module => module.default(url, init));

不幸的是,雖然這似乎滿足 TypeScript 編譯器,但我在自己的代碼中發現運行時仍然不起作用(拋出ERR_REQUIRE_ESM ),因為我的 TypeScript 配置當前使用的是 CommonJS 模塊而不是 ESM 格式。

有關與此問題相關的節點獲取 package 中的幾個未解決問題,請參閱https://github.com/node-fetch/node-fetch/issues?q=ERR_REQUIRE_ESM

本質上,node-fetch 維護者建議我們這些使用 TypeScript 的人需要轉換為 ESM 模塊,遠離 CommonJS(參見https://github.com/node-fetch/node-fetch/issues/1397#issuecomment-97809216和后續評論)。

降級或安裝 v2。 npm install node-fetch@2 && npm install --save-dev @types/node-fetch@2.x

當節點不支持 ESM 3.x 時,ESM 3.x 有什么意義? 至少對於 tsc。 也許 ts-node 支持它。 但 tsc 應該與 ts-node 兼容。

import { default as fetch, Headers } from 'node-fetch';

配置文件

{
    "$schema": "https://json.schemastore.org/tsconfig",
    "display": "Node 12",
    "compilerOptions": {
      "lib": ["es2019"],
      "module": "commonjs",
      "target": "es2019",
      "strict": true,
      "esModuleInterop": true,
      "skipLibCheck": true,
      "forceConsistentCasingInFileNames": true,
      "moduleResolution": "node"
    },
    "include": [
        "**/*.ts"
    ]
  }

注意:節點 14,將 tsconfig 從上面的 es2019 更新為 es2020 & 顯示節點 14

我建議使用cross-fetch ,它幾乎相同,但在任何地方都可以使用,它對我有幫助,因為我無法在 TypeScript 中運行 node-fetch

這個設置對我有用:

package.json

{
  "main": "index.ts",
  "scripts": {
    "start": "ts-node --esm ./src/index.ts"
  },
  "type": "module",
  "dependencies": {
    "@types/node": "^18.11.18",
    "@types/node-fetch": "^2.6.2",
    "node-fetch": "^3.3.0",
    "nodemon": "^2.0.20",
    "ts-node": "^10.9.1",
    "typescript": "^4.9.5"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "lib": ["ES2022", "DOM"],
    "module": "ES2022",
    "moduleResolution": "node",
    "target": "ES2022",
    "esModuleInterop": true,
  }
}

索引.ts

import fetch, { Headers } from 'node-fetch';
// do something

我使用的是 ts-node,所以請注意您需要應用--esm兼容性:

ts-node --esm./src/index.ts

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM