Type definition generated for CommonJS output using `module.exports = ` is not usable
Problem
The type definition file generated for CommonJS output using module.exports = syntax is not consumable by TS projects without esModuleInterop enabled or JS projects with type checking or editors with support for type hints on JavaScript files.
For example, given this TypeScript input:
// src/index.ts
export default function Foo() {}
The JavaScript file generated when using pkgroll v2.0.1 will be:
// dist/index.cjs
module.exports = function Foo() {}
And this will be created along with the following type definition:
// dist/index.d.cts
declare function Foo(): void;
export { Foo as default };
However, when a project using CommonJS modules consumes the compiled files like so:
// @ts-check
const Foo = require('./dist/index.cjs');
new Foo()
Then they will receive the following error when running a type check on their code or attempting to use type hints in their editor because these are expecting the implementor to reference a property named "default":
This expression is not constructable.
Type 'typeof import("/Users/matthinchliffe/Code/test-case/dist/index")' has no construct signatures.ts(2351)
Because there's no equivalent of module.exports = with ESM the Rollup documentation suggests always using named export mode to avoid creating two different interfaces:
In other words for those tools, you cannot create a package interface where
const lib = require("your-lib")yields the same asimport lib from "your-lib". With named export mode however, const {lib} = require("your-lib") will be equivalent to import {lib} from "your-lib".
So whilst neither of these may be ideal I understand there are two potential solutions for this problem:
- Manipulate the type definition to output
export =syntax. - Use Rollup's
namedexport mode to outputexports.default =
(p.s. apart from this hiccup, the project has been A+, thank you)
Expected behavior
The module imported using require should have the correct type definition applied and editor type hints enabled. The following type definition would work:
declare function Foo(): void;
export = Foo;
Alternatively, the following generated JS would work:
exports.default = function Foo() {}
Minimal reproduction URL
https://gist.github.com/i-like-robots/29b8662210f6898626f40d49e8e39e68
Version
v2.0.1
Node.js version
v18.18
Package manager
npm
Operating system
macOS
Contributions
- [ ] I plan to open a pull request for this issue
- [ ] I plan to make a financial contribution to this project