typescript 使用import from 方式引入自建对象时报错模块未找到,且已设置moduleResolution为node?

Nodejs项目使用import {a,c} from "./xxx/xxx" 方式导入的时候出现异常,必须要附带后缀名".ts"或者".js"才行,如"import {a,c} from "./xxx/xxx.js":

node:internal/process/esm_loader:40
      internalBinding('errors').triggerUncaughtException(
                                ^
Error: Cannot find module 'C:\Users\admin\WebstormProjects\untitled\src\bot\events' imported from C:\Users\admin\WebstormProjects\untitled\index.ts

其中index和events都是ts对象,从报错中看貌似没有去寻找events.ts文件

Node.js V20.9.0
ts-node V10.9.1

我已经完成了tsconfig.json的配置,而且删除了babel之类的相关依赖,依然无法解决问题

  "compilerOptions": {
    "outDir": "dist",
    "types": [
      "node",
      "jest"
    ],
    "moduleResolution": "node",
    "module": "ESNext",
    "target": "ESNext"
  }

如果说我带上了".ts"后缀,IDE会提示我:An import path can only end with a  .ts  extension when  allowImportingTsExtensions  is enabled;
image.png

image.png

image.png
如果说我带上了".js"后缀,那么可以正常运行,但是在IDE的自动补全导入代码的时候并不会主动给我带上".js"后缀,很不方便,所以我想知道为什么我这里不能在没有后缀的时候引入依赖对象

阅读 1.3k
avatarAI BotBETA

这个问题可能是由于 TypeScript 的模块解析行为与 Node.js 不同导致的。在 TypeScript 中,当你使用 import {xxx} from "./xxx/xxx" 这样的语法时,TypeScript 会尝试找到 ./xxx/xxx 这个路径下的 xxx.tsxxx.d.ts 文件。在你的情况下,它没有找到 events.ts 文件,所以报错了。

要解决这个问题,你可以尝试以下几种方法:

  1. 确保你的 tsconfig.json 文件中的 moduleResolution 选项设置为 node。你已经正确地做了这一步。
  2. 确保你的导入路径是正确的。如果 ./xxx/xxx 是一个文件夹,那么你应该在该文件夹下有一个 index.ts 文件,或者一个 export 语句导出的文件。例如,你可以尝试将你的导入语句更改为 import {xxx} from "./xxx/xxx/index"import {xxx} from "./xxx/xxx/myfile",其中 myfile 是你实际想要导入的文件。
  3. 如果你在使用 TypeScript 的最新版本(v4.0+),你可以尝试使用 import {xxx} from "./xxx/xxx"; 这种导入语法,而不需要指定文件后缀。这是因为在 TypeScript v4.0+ 中,已经支持使用 ES6 的 import 语法直接导入 JavaScript 或 TypeScript 文件,而不需要指定 .js.ts 后缀。如果你的 IDE 没有自动添加后缀,可能是因为你的 TypeScript 版本过旧,或者 IDE 没有正确地配置。
  4. 如果以上方法都无法解决问题,你可能需要检查一下你的 Node.js 和 TypeScript 的版本。Node.js v20.9.0 和 ts-node v10.9.1 已经有些过时了,可能有更新的版本可以解决你的问题。你可以尝试升级 Node.js 和 TypeScript 到最新版本。

希望这些建议能帮助你解决问题!

3 个回答
✓ 已被采纳

在搜索了无数的资料后得到答案,因为我使用的typescript版本比较高,新版本的ts特性会要求使用相对路径导入的时候带上文件扩展名以提升性能

举例来说,NodeJs 中的 ESM 强制要求你的相对导入路径携带扩展名,即 import ns from "./mod.mjs"(你也可以使用 --experimental-specifier-resolution=node 配置来启用自动地路径解析),这主要是为了贴合 NodeJs 在服务器环境下的性能表现。然而大部分的构建工具其实不要求你这么做,它会融合 ESM 与 CJS 的模块解析策略。

所以,只需要在package.json中带上“--experimental-specifier-resolution=node”指令即可
如:

cross-env NODE_OPTIONS="--no-warnings --loader=ts-node/esm --experimental-specifier-resolution=node " node index.ts

参考:TS 5.0 新特性

想要vscode自动给你带上.js后缀可以配置如下:

{
    "typescript.preferences.importModuleSpecifierEnding": "js",
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏