typescriptbeginner

ESM and CJS Module Interop

Handle ECMAScript module and CommonJS interop with dynamic imports, conditional exports, and dual packages.

typescript
// === ESM Module (math.mts) ===
// Named exports
export function add(a: number, b: number): number {
  return a + b;
}

export function multiply(a: number, b: number): number {
  return a * b;
}

// Default export
export default { version: '1.0.0' };

// === Importing CJS from ESM ===
// Dynamic import (works in both ESM and CJS)
async function loadCjsModule() {
  // import() works for CJS modules in ESM context
  const fs = await import('fs');
  const path = await import('path');
  console.log(path.resolve('.'));
}

// === CJS consuming ESM (must use dynamic import) ===
// In a .cjs file:
// async function main() {
//   const { add, multiply } = await import('./math.mjs');
//   console.log(add(2, 3));
// }

// === Dual Package pattern (package.json) ===
const dualPackageJson = {
  name: 'my-lib',
  type: 'module',
  main: './dist/cjs/index.cjs',   // CJS entry
  module: './dist/esm/index.js',  // ESM entry
  types: './dist/types/index.d.ts',
  exports: {
    '.': {
      import: {
        types: './dist/types/index.d.ts',
        default: './dist/esm/index.js',
      },
      require: {
        types: './dist/types/index.d.cts',
        default: './dist/cjs/index.cjs',
      },
    },
    './utils': {
      import: './dist/esm/utils.js',
      require: './dist/cjs/utils.cjs',
    },
  },
};

// === __dirname / __filename in ESM ===
import { fileURLToPath } from 'url';
import { dirname } from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

console.log('Current file:', __filename);
console.log('Current dir:', __dirname);

// === Detect module system ===
function isESM(): boolean {
  return typeof import.meta !== 'undefined';
}

export { dualPackageJson, loadCjsModule };

Use Cases

  • Library dual packaging
  • Migration from CJS to ESM
  • Cross-module-system compatibility

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.