如何将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版本现在提供了原生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
变量,然后重用了名称";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