使用 require 时出现打字稿错误 - 此表达式不可调用。类型“typeof import(...)”没有调用签名.ts(2349)
Posted
技术标签:
【中文标题】使用 require 时出现打字稿错误 - 此表达式不可调用。类型“typeof import(...)”没有调用签名.ts(2349)【英文标题】:Typescript error when using require - This expression is not callable. Type 'typeof import(...)' has no call signatures.ts(2349) 【发布时间】:2021-10-30 21:26:28 【问题描述】:我正在尝试运行此脚本
const fetch = require('node-fetch');
function test()
fetch('https://google.com')
.then(res => res.text())
.then(text => console.log(text))
test();
但我得到了这个错误
此表达式不可调用。 类型 'typeof import("(...)/node_modules/node-fetch/@types/index")' 没有调用 signatures.ts(2349)
虽然它在我使用 import 时有效
import fetch from 'node-fetch';
为什么以及如何解决它?
【问题讨论】:
很可能默认导出在模块的default
属性上。 const default as fetch = require('node-fetch')
如何解决?
对不起,我试过 const fetch as fetch = require('node-fetch');但我得到了“模块”“node-fetch”,没有导出的成员“fetch”。您的意思是改用“从“node-fetch”导入获取吗?ts(2614)'
另外 npm 页面提到:'node-fetch 是一个 ESM-only 模块 - 你不能用 require 导入它。我仍在尝试这样做,因为我的文件还需要加载 json。你会如何解决这个问题?让所有东西都导入?
如果可以使用import
,为什么还要使用require
?我也想你可以import
jsons,但如果失败,你可以使用import
用于模块,require()
用于 json 文件
@ObaApi 哎呀。抱歉,我对 import
语法感到困惑。我的意思是const default : fetch = require('node-fetch')
【参考方案1】:
根据spender的comment,您可以更改使用此解构的要求:
const default : fetch = require('node-fetch');
这在类似情况下对我有用(在节点中使用 axios,它具有类似的 API)
【讨论】:
【参考方案2】:您有以下选择:
-
自己使用 ESM。 (首选)
使用
import foo from 'node-fetch'
而不是const fetch = require('node-fetch')
来导入包。您还需要将 "type": "module"
放入您的 package.json 等。请遵循以下指南。
如果包在异步上下文中使用,您可以使用 CommonJS 中的 await import(…)
而不是 require(…)
。
在您可以迁移到 ESM 之前,请继续使用现有的 2.x 版本的 node-fetch。
我强烈建议迁移到 ESM。 ESM仍然可以导入CommonJS包,但是CommonJS包不能同步导入ESM包。
Node.js 12 及更高版本原生支持 ESM。
如何将我的 CommonJS 项目迁移到 ESM?
将"type": "module"
添加到您的package.json。
将 package.json 中的 "engines"
字段更新为 Node.js 12:"node": ">=12.20.0"
。
从所有 javascript 文件中删除 'use strict';
。
将所有require()
/module.export
替换为import
/export
。
仅使用完整的相对文件路径进行导入:import x from '.';
→ import x from './index.js';
。
如果您有 TypeScript 类型定义(例如,index.d.ts
),请将其更新为使用 ESM 导入/导出。
可选但建议使用 node:
protocol 进行导入。
我可以在我的 TypeScript 项目中导入 ESM 包吗?
可以,但您需要将项目转换为输出 ESM。见下文。
如何让我的 TypeScript 项目输出 ESM?
将"type": "module"
添加到您的 package.json。
在您的 package.json 中将 "main": "index.js"
替换为 "exports": "./index.js"
。
将 package.json 中的 "engines"
字段更新为 Node.js 12:"node": ">=12.20.0"
。
将"module": "ES2020"
添加到您的 tsconfig.json。
仅使用完整的相对文件路径进行导入:import x from '.';
→ import x from './index.js';
。
删除 namespace
用法并改用 export
。
可选但建议使用 node:
protocol 进行导入。
即使要导入 .ts
文件,也必须在相对导入中使用 .js
扩展名。
如果您使用ts-node
,请关注this guide。
如何导入 JSON?
JavaScript 模块最终会得到native support for JSON,但现在,你可以这样做:
import promises as fs from 'node:fs';
const packageJson = JSON.parse(await fs.readFile('package.json'));
如果您以 Node.js 14 或更高版本为目标,则可以改用 import fs from 'node:fs/promises';
导入它。
【讨论】:
我认为这不是绝对必要的,所以我对暗示这一点投了反对票 另外,当你从他们那里复制和粘贴时,你应该给予他们信任...gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c以上是关于使用 require 时出现打字稿错误 - 此表达式不可调用。类型“typeof import(...)”没有调用签名.ts(2349)的主要内容,如果未能解决你的问题,请参考以下文章