question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

"moduleResolution": "NodeNext" throws ESM related errors

See original GitHub issue

Does this issue occur when all extensions are disabled?: Yes

  • VS Code Version: 1.69.2
  • OS Version: macOS 12.4
  • TypeScript Version: 4.7.4

Steps to Reproduce:

  • Create an npm package. Install typescript@4.7.4 and pretty-ms.
  • Set tsconfig.json as:
{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "esnext"],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "module": "NodeNext",
    "moduleResolution": "NodeNext"
  },
  "include": ["./src/**/*"]
}
  • Add "type": "module" in package.json
  • Following error messages are displayed by VSCode in a file with .ts extension under src/:
// Cannot find module 'pretty-ms' or its corresponding type declarations. ts(2307)
import ms from "pretty-ms";

// The 'import.meta' meta-property is not allowed in files which will build into CommonJS output. ts(1470)
console.log(import.meta.url);
  • tsc throws no errors.
  • Change below values intsconfig.json
{
  "module": "esnext",
  "moduleResolution": "node"
}
  • VSCode no longer throws any errors.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:9
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

7reactions
egasimuscommented, Sep 19, 2022

The main issue with ESM and nodenext/node16 mode is TypeScript refusing to add .js extensions to the generated import statements in the compiled files.

The officially proposed workaround is to manually add .js extensions in the TypeScript sources, which is particularly graceless. So .ts extension is disallowed, yet .js extension is required in order to point to a .ts file - what the fuck? And where do .d.ts files even fit into this?

It’s particularly surprising because TypeScript encourages you to use import and export statements even when compiling to CJS. And when you combine this broken behavior with Node’s half-assed effort to push people off CommonJS and onto ESM, this hits real hard if you’re using monorepos/workspaces/submodules/writing a library.

Frontend framework users whose build toolchain compiles TypeScript on demand will be hit next as they add the .js extensions and their code stops updating. Frameworks will have to special-case this kludge and it’ll become 10x harder for a newcomer to understand how JS modules work.

It makes my team members develop an aversion to TypeScript, not to mention it probably got me looking pretty bad myself, because the only way to perform the otherwise trivial act of delivering an isomorphic library (i.e. one which which works out of the box in all contexts - Node, browser, ESM, CJS, pre-compiled, on-demand, framework, no framework) is walking the compiled code’s AST to add the extensions.

1reaction
kachkaevcommented, Nov 1, 2022

I’m facing the same issue in these two PRs:

Here are some third-party packages that have problems with default exports when "moduleResolution": "NodeNext" or "moduleResolution": "Node16":

  • ajv
  • styled-components
  • algoliasearch
  • next/link, next/document, next/image, etc.
  • react-slick
  • @mui/icons-material/*
  • react-gtm-module
  • @emotion/cache
  • react-html-parser
  • slugify

As a temp solution, I’ve managed to do this:

-import x from "x";
+import _x from "x";
+const x = _x as unknown as typeof _x.default;

Although it‘s true that the problem is within the packages, I wonder if it is possible to create a new compile option which could be used during the transition period? Something like allowSyntheticDefaultImports, but for a different use case.

When switching a project to "moduleResolution": "NodeNext", it’s much easier to negotiate one extra line in tsconfig.json than a lot of import _x from "x" hacks. Waiting for upstream fixes may take a while and slow down migration to ESM.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript and native ESM on Node.js - 2ality
In this blog post, I'll explain everything you need to know in order to use and produce native ECMAScript modules on Node.js.
Read more >
Why compiler is throwing error on await in async function.?
My compiler options in ts.config files are { "compilerOptions": { "target": "ES2022", /* Set the JavaScript language version for "module": ...
Read more >
TSConfig Reference - Docs on every TSConfig option
An error occurs if any of the files can't be found. ... node16. nodenext. Related: moduleResolution. Released: ... finally { if (e_1) throw...
Read more >
ES Modules in NodeJS - Troubleshooting Resources
Assorted Errors and Issues · If you are using the ESM loader, you need to specify the file extension (see error above this...
Read more >
at new nodeerror (node:internal/errors:372:5) - You.com
I also face this issue sometimes whenever I've Debugger enabled in the Vs Code and I console.log(error) It is not related to any...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found