Named export 'Types' not found. The requested module 'mongoose' is a CommonJS module, which may not support all module.exports as named exports
Asked Answered
D

2

41

I have an express server written in typescript with "module": "es2020" in its tsconfig.

I've also developed another es2020 module for my graphql API, still in typescript, and this module uses mongoose with such named imports:

import { Types } from 'mongoose'

Everything works fine when I compile my graphql module with tsc. But the express server which is ran with

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

is unable to handle the mongoose named import.

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;

Solution #1

import mongoose from 'mongoose'

And replace Types by mongoose.Types.

But since tsc can handle the mongoose named import, I have hope that it's also possible to make ts-node able to do so.

Solution #2

Switch to commonjs, I can keep the import/export syntax in my graphql module and compile it as a cjs module. But I would have to use a cjs syntax in my express server, and I don't want to.

Dailey answered 6/1, 2022 at 9:55 Comment(4)
Even though @types/mongodb says it's deprecated, I still use the package and can then use named imports.Bourg
@LucaKiebel Adding @types/mongodb to my module won't make me able to use mongoose named import with ts-node, btw I'm not only importing Types from mongoose, in some other files I'm importing Schema and Model. And I'm facing the same errorDailey
@Ashitaka did you find a solution?Endres
@MrPablo I didn't find a real solution, so I've chosen to build my express server with tsc before running it with node, which works fine, but I have to rebuild and start the server after each modificationDailey
S
29

TL;DR

All you have to do is remove the curly braces from the Types. That should work. Just like this:

import Types from 'mongoose'

But the name does not matter.

Explanation

import Types from 'mongoose' works because we are importing the package's default export (this is why the name we use does not matter).

However, when you do import * as Types from 'mongoose you tell JS that you seriously want everything as it is raw. That means that instead of getting the default export:

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

You get this:

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

So you could have also done Types.default but that's probably not as clean. 🙂

This StackOverflow post suggests that we could make both work, but also suggests it would be a hacky workaround that probably should not work 😓

Simultaneous answered 8/3, 2022 at 16:28 Comment(2)
What is the import statement is causing the issue is within node_modules (ie. external libraries)?Nomarchy
This answer explains some differences in import statements but it doesn't address the question asked in any way. This is a specific error thrown when trying to import what amounts to a CommonJS named export by name using a module import statement. tsc handles this fine, ts-node with Jest handles this fine, but ts-node by itself seems to fail working with these imports and this quesiton is asking why that is.Dendy
S
9

If you encounter this error having a mono-repo, make sure the module that you have problems with, has

"type": "module" 

in package.json.

It seems that Nodejs will consider packages to be commonjs by default and you need to explicitly tell it that your package is a module.

Slipknot answered 4/5, 2023 at 17:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.