Alexander Craggs
Alexander Craggs

Reputation: 8759

How do I make a ESM / CJS module that doesn't require adding '.default' to the imports

I can setup my package.json to use different imports for CJS and ESM:

  "main": "dist/cjs/index.js",
  "module": "dist/esm/index.js",

I can also setup my TypeScript compiler to create two distributions:

// for ESM
{
  "compilerOptions": {
    "module": "es2020",
    "target": "es2015",
    "declaration": true,
    "esModuleInterop": true,
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist/esm"
  },
  "include": [
    "src/**/*"
  ]
}
// for CJS
    "extends": "./tsconfig.json",
    "compilerOptions": {
        "module": "CommonJS",
        "outDir": "./dist/cjs"
    },

And I can run both of them using tsc to produce a dist folder with both a cjs and esm folder:

"build": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json"

However, when I test this, I seem to require adding .default to both my examples:

// CJS
const someClass = require('package').default
const instance = new someClass()

// ESM
import someClass from 'package'
const instance = new someClass.default("")

How can I avoid the added .default required in both examples?

My package simply exports a single class:

import someClass from './class';

export default someClass;

Where class is also simple:

class someClass { constructor() {} }

export default someClass

Upvotes: 4

Views: 1465

Answers (1)

brunnerh
brunnerh

Reputation: 184526

An export without default requires different syntax:

class someClass { constructor() {} }

export = someClass

(To import an export like this in a TypeScript project you need to set the esModuleInterop flag.)

Upvotes: 1

Related Questions