在使用TypeScript的Node项目中如何正确导入node-fetch包?
问题原因
- 第一个
Cannot redeclare block-scoped variable 'fetch'报错:Node.js 18及以上版本内置了全局fetchAPI,对应的@types/node类型声明中已经定义了全局fetch变量,你自行声明同名变量就会触发块级变量重复声明错误,不需要必须修改变量名,调整配置或者用其他导入方案即可解决。 - 第二个
A spread argument must either have a tuple type or be passed to a rest parameter报错:你写的动态导入代码没有给args参数定义类型,TS无法判断传入的参数符合fetch的入参要求,触发类型校验错误。 - React项目可以直接使用
import fetch from 'node-fetch'的原因:React项目的构建工具(webpack/vite等)默认支持ESM模块转译,不管源包是ESM还是CommonJS都能处理。而node-fetch从v3版本开始改为纯ESM包,仅支持import静态导入,不支持CommonJS的require导入,如果你的Node项目TS配置是输出CommonJS模块(tsconfig.json中module字段为CommonJS),就无法直接静态导入node-fetch v3,才需要写动态导入逻辑。
解决方案(优先级从高到低)
方案1:直接使用Node.js原生fetch(推荐)
如果你的Node.js版本是18.x及以上,完全不需要安装node-fetch包,直接在代码中调用全局fetch()方法即可。如果TS报错找不到fetch类型,做以下任意一个操作即可:
- 升级
@types/node到最新版本 - 在
tsconfig.json的compilerOptions.lib数组中加入DOM
方案2:将项目改为ESM模式
如果你需要使用node-fetch v3的特性,可以直接把项目调整为ESM模块标准,和React项目的导入写法完全一致:
- 在项目
package.json中新增字段"type": "module" - 修改
tsconfig.json配置:
{ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext", // 其余配置保持不变 } }
- 直接用
import fetch from 'node-fetch'导入使用即可。
方案3:使用兼容CommonJS的node-fetch v2版本
如果你不想修改现有项目的模块配置,可以安装支持CommonJS的node-fetch v2版本:
- 安装对应版本包和类型:
npm install node-fetch@2 npm install -D @types/node-fetch@2
- 直接导入使用即可:
import fetch from 'node-fetch' // 或者 const fetch = require('node-fetch')
方案4:修正现有动态导入写法
如果你一定要保留现有的动态导入逻辑又不想修改变量名,可以给代码加上类型声明,同时避免和全局fetch的类型冲突:
import type { RequestInfo, RequestInit, Response } from 'node-fetch' // 覆盖全局fetch类型声明,避免重复声明报错 declare global { var fetch: typeof import('node-fetch').default } globalThis.fetch = (...args: [RequestInfo, RequestInit?]): Promise<Response> => import('node-fetch').then(({ default: fetch }) => fetch(...args))
修改完成后即可直接在项目中调用fetch()方法。
内容的提问来源于stack exchange,提问作者Sowam
相关产品推荐
相关产品推荐

