正在使用typescript导入节点项目中的节点获取



如何将node-fetch包导入到使用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包?在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';

替代解决方案:如果您需要使用以浏览器为中心构建并需要全局获取的第三方库,请查看isomorphic-fetch模块,该模块添加了fetch作为全局函数。

您需要导入一次,以便fetch在全球可用:

import 'isomorphic-fetch';

在这种情况下,tsconfig.json的编译器选项应该包含dom库。

更新2022-02-04

较新的NodeJS版本现在提供了原生fetchAPI,因此以后不再需要上述版本。请参阅此处和此处了解更多信息。

更新:

我在下面的原始帖子都是真的。然而,我已经能够让它发挥作用,而不必切换到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变量,然后重用了名称";CCD_ 22";作为该行稍后CCD_ 23回调的对象析构函数参数。

因此,将行更改为如下读取可以清除该错误:

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格式。

请参阅https://github.com/node-fetch/node-fetch/issues?q=ERR_REQUIRE_ESM有关nodefetch包中与此问题相关的几个打开的问题。

从本质上讲,节点获取维护人员建议我们这些使用TypeScript的人需要转换到ESM模块,而不是CommonJS(请参阅https://github.com/node-fetch/node-fetch/issues/1397#issuecomment-978092116及其后的评论)。

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

当节点不支持ESM3.x时,它有什么意义?至少对于tsc。也许ts节点支持它。但是tsc应该与ts节点。

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

tsconfig

{
"$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

此外,Node 17+fetch是内置的。所以,当ESM在节点中得到支持时,您可能不需要获取节点。

我建议使用交叉提取,它几乎相同,但在任何地方都有效,它对我有帮助,因为我无法在TypeScript 中运行节点提取

这个设置对我有效:

软件包.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,
}
}

index.ts

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

我使用的是ts节点,所以请注意,您需要应用--esm兼容性:

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

最新更新