What is the equivalent of module.exports for ES6 Modules?

Viewed 1373

I have an existing package written in JavaScript that I'm trying to convert to TypeScript. My question is, what is the equivalent of module.exports for ES6 Modules?

For example if I have the following code:

module.exports = function () {
    console.log("Hello World");
};

The only way I have found to do this in ES Modules is by doing something like the following.

const myFunc = function () {
    console.log("Hello World");
};
export default myFunc;
// OR
export { myFunc };

Of course, this is not the same thing as module.exports = //....

Which leads to this problem. When I run this through TypeScript and get the outputted code, users of the package will either need to use an import defaultExport from "module-name"; statement (which isn't bad), or instead of being able to access it using require("module-name") they will have to use require("module-name").default (if they are using standard JS, not TypeScript). Which obviously is a breaking API change for standard JavaScript users.

Obviously, the goal here is to have no breaking API changes (and require no changes for customers code).


One more requirement to any solution. In other places in the package I need to be able to export a lot of different files as one object. So in the past I've been doing:

module.exports = {
    "thing1": require("./a.js"),
    "thing2": require("./b.js")
};

So I need to be able to export this as normal without requiring the user to do thing1.default. This one so far seems like the easier requirement since I'm exporting an object which ES Modules seems to handle really well. It's when you are exporting a singular (non-named) expression that it gets really tricky.


Is there a way to do this without having to make this a breaking change to the API?

3 Answers

The solution here is to use the TypeScript export = command. This allows you to use either require or import with the module.

export = function () {
    console.log("Hello World");
};
import myModule from "./lib/myModule";

// OR

const myModule = require("./lib/myModule");

For more information the TypeScript documentation has a guide about Migrating from JavaScript, and specifically a section called Exporting from Modules.

Typescript recommends not to rewrite your code, but instead to configure it to allow js modules.

When we were working on converting a very large app from js to TS, we took the position of writing new code in TS, and slowly converting js into ts (but not spend a whole lot of time just converting).

We needed to enable few options in the tsconfig.json, such as :

{
  ...,
  "compilerOptions" : {
    ... 
    "moduleResolution": "node",
    "allowJs": true,
    ...
  },
  "include" [
    "path/to/my/js",
  ]
}

you also need to update your webpack.config.js:

module.exports = {
   // ... my settings


   resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
    },
}

You might also have to declare require as a function (if you are getting errors such as require is undefined):

declare function require(path: string): any;

more info is available here : https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html

Most accurate replacement for module.exports in typescript is export default

export default {
    "thing1": require("./a.js"),
    "thing2": require("./b.js")
}

then you can use them like below

import myThings from '.....'
Related