使用 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)的主要内容,如果未能解决你的问题,请参考以下文章

将模糊搜索与猫鼬一起使用时出现打字稿错误

将模糊搜索与猫鼬一起使用时出现打字稿错误

编译节点模块时出现打字稿错误

在 AOT 中构建 Angular 模块时出现打字稿错误

使用带有打字稿的 react-bootstrap Form.Label 时出现类型错误

使用带有 lit-html 的打字稿编写测试时出现“语法错误:无法在模块外使用 import 语句”