命名导出 'Types' 未找到。所请求的模块 'mongoose' 是一个 CommonJS 模块,可能不支持所有模块输出作为命名导出。

29

我有一个用TypeScript编写的Express服务器,它的tsconfig中使用了"module": "es2020"

我还开发了另一个用TypeScript编写的es2020模块,用于我的GraphQL API,并且这个模块使用mongoose,其命名导入如下:

import { Types } from 'mongoose'

当我使用tsc编译我的GraphQL模块时,一切都很正常。但是,使用以下命令运行的Express服务器无法处理mongoose的命名导入:

nodemon --watch './**/*.ts' --exec 'node --experimental-specifier-resolution=node --loader ts-node/esm' src/index.ts

import { Types } from 'mongoose';
         ^^^^^
SyntaxError: Named export 'Types' not found. The requested module 'mongoose' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'mongoose';
const { Types } = pkg;

解决方案 #1

import mongoose from 'mongoose'

Types 替换为 mongoose.Types

但由于 tsc 可以处理 mongoose 的命名导入,我希望 ts-node 也可以这样做。

解决方案 #2

切换到 commonjs,我可以在我的 graphql 模块中保留 import/export 语法并将其编译为 cjs 模块。但我必须在我的 express 服务器中使用 cjs 语法,而我不想这样做。


尽管@types/mongodb已经被标记为过时,但我仍然使用该软件包,并且可以使用命名导入。 - Luca Kiebel
@LucaKiebel 将 @types/mongodb 添加到我的模块中并不能让我在使用 ts-node 时使用 mongoose 命名导入,顺便说一下,我不仅从 mongoose 中导入 Types,在其他一些文件中我还导入了 SchemaModel。而且我面临着同样的错误。 - 0xChqrles
@Ashitaka,你找到解决方案了吗? - Mr Pablo
1
@MrPablo,我没有找到真正的解决方案,所以我选择在使用node运行之前使用tsc构建我的express服务器,这个方法很好用,但是每次修改后都需要重新构建和启动服务器。 - 0xChqrles
2个回答

27

简述

你只需要从类型中删除花括号,就可以使其起作用。就像这样:

import Types from 'mongoose'

但是名称并不重要。

说明

import Types from 'mongoose' 能够正常工作,是因为我们导入了该包的默认导出(这就是为什么我们使用的名称并不重要)。

然而,当你使用 import * as Types from 'mongoose' 时,你告诉JS你真的想要所有未经加工的内容,这意味着你不会得到默认导出:

{
    "function1": {},
    "function2": {}
}

你会得到这个:

{
    "default": {
        "function1": {},
        "function2": {}
    }
}

那么你也可以使用Types.default,但这可能不够简洁。

这篇StackOverflow文章建议我们可以让两种方式都起作用,但同时也表示这将是一个粗糙的解决方法,可能不应该生效


4
导入语句是否引起问题在于 node_modules(即外部库)中? - blomster

4
如果您在使用单一代码库时遇到此错误,请确保出现问题的模块已经...。
"type": "module" 

package.json 文件中。

似乎 Nodejs 默认将包视为 commonjs,您需要明确告诉它您的包是一个模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接