TypeScript: Typescript [4.8.2] is adding invalid javascript for *.cjs files

Bug Report

My project is set to emit ESNext modules. I have a variety of TS files, but I also have a single .cjs file, which needs to remain CommonJS to try and require legacy packages.

My input looks like this:

module.exports = {
  tryRequire(modulePath) {
    return require(modulePath);
  },
};

I expect the output I get from TypeScript 4.7.4:

module.exports = {
  tryRequire(modulePath) {
    return require(modulePath);
  },
};

When I upgrade to TypeScript 4.8.2, it now emits an extra export {} at the end of the .cjs file:

module.exports = {
  tryRequire(modulePath) {
    return require(modulePath);
  },
};
export {}

This causes Node to fail parsing the .cjs file because export does not exist in the .cjs context.

🕗 Version & Regression Information

Worked in 4.7.4, broken in 4.8.2, also broken in current nightly (4.9.0-dev.20220905).

Repro here

https://github.com/dzearing/ts-repro-cjs

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 21 (10 by maintainers)

Most upvoted comments

FYI, the "module": "nodenext" solution does not work if you also need "moduleResolution": "bundler". In my case I’m using bundler because it matches the behavior of my node loader (extensionless and subpath exports).

Option 'bundler' can only be used when 'module' is set to 'es2015' or later.

@weswigham honestly, I think we should consider making export default in CJS-scoped declaration files an error under node16/nodenext, with a message that says the library is probably wrong, similar to #52173. That’s a super common mistake that can often be overlooked in --moduleResolution node.

Ah thank you! You’re right; turns out I needed to import clsx as:

import { clsx } from "clsx";

My ts build now works with module: nodenext, and the empty export is gone.

I am unblocked here. I do still think it’s not ideal to be emitting invalid cjs but at least I have a workaround. 😃

Yes! That fixed it. I changed to module: "nodenext" and added type: "module" to the package.json to achieve the expected output (ESM by default, CJS for cjs files.)