How to fix Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'es5' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 11, 2025· 113 views

This TypeScript configuration error occurs when you try to use the modern 'esnext' module system with legacy JavaScript targets (ES3 or ES5). The esnext module format requires modern JavaScript features that aren't available in older ECMAScript versions. To fix this, either upgrade your target to ES2015+ or switch to a compatible module system like CommonJS.

Quick fix

Fixes Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'es5'

// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",      // ← This is the problem
    "target": "es5",         // ← Incompatible with esnext
    // ... other options
  }
}
  1. Check your current tsconfig.json settings
  2. Upgrade target to ES2015 or later
  3. Change module to a compatible format
  4. Check extended configurations and overrides
typescript — error
// tsconfig.json
{
"compilerOptions": {
"module": "esnext", // ← This is the problem
"target": "es5", // ← Incompatible with esnext
// ... other options
}
}
Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'es5'

What this error means

The "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'es5'" error appears when there's an incompatibility between your TypeScript compiler settings in tsconfig.json. The `module` option controls how TypeScript generates module code (import/export statements), while the `target` option determines which ECMAScript version your code compiles to. The 'esnext' module system uses modern JavaScript module syntax that requires features only available in ES2015 (ES6) and later. ES3 (1999) and ES5 (2009) are legacy JavaScript versions that don't support: - ES modules (`import`/`export` syntax) - Arrow functions (used in some module transformations) - Modern class syntax - Other ES6+ features that TypeScript's 'esnext' module output may rely on TypeScript prevents this combination because the generated code would be invalid JavaScript for your target environment. You need to either: 1. Upgrade your `target` to ES2015 or later to use modern module systems 2. Change your `module` to a format compatible with ES3/ES5 (like 'commonjs' or 'umd')

Typical symptoms

  • TypeScript compilation fails with the exact error message
  • Build process (tsc, webpack, etc.) stops with this configuration error
  • IDE/editor shows red squiggles in tsconfig.json file
  • Error appears immediately after modifying tsconfig.json
  • Project fails to compile even though code syntax is correct
  • CI/CD pipeline fails during TypeScript compilation step

Common causes

  1. Setting 'module' to 'esnext' while 'target' is 'es3' or 'es5' in tsconfig.json
  2. Inheriting tsconfig settings from a base configuration with incompatible values
  3. Using a template or starter project with mismatched compiler options
  4. Accidentally downgrading 'target' while keeping 'module' as 'esnext'
  5. Copy-pasting tsconfig.json from a modern project into a legacy one
  6. Using tools that auto-generate tsconfig.json with incompatible defaults
  7. Migrating from JavaScript to TypeScript without updating compiler options

How to fix "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'es5'"

1Check your current tsconfig.json settings

First, examine your tsconfig.json file to see the current module and target values:

json
// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",      // ← This is the problem
    "target": "es5",         // ← Incompatible with esnext
    // ... other options
  }
}

Look for these lines in your configuration. The error specifically mentions the combination of 'module: esnext' with 'target: es3' or 'target: es5'.

You can also check from the command line:

bash
# Show effective TypeScript configuration
npx tsc --showConfig

# Or check specific files
cat tsconfig.json | grep -E "(module|target)"
2Upgrade target to ES2015 or later

The simplest fix is to upgrade your target to a modern ECMAScript version that supports ES modules:

json
{
  "compilerOptions": {
    "module": "esnext",
    "target": "es2015",      // ← Changed from es5 to es2015
    "lib": ["es2015", "dom"],
    // ... other options
  }
}

Recommended targets:
- ES2015 (ES6): Minimum for ES module support
- ES2017: Good balance of compatibility and modern features
- ES2020: Modern JavaScript with latest features
- ESNext: Latest ECMAScript features (experimental)

Consider your deployment environment:
- Node.js: Check your Node version compatibility
- Browsers: Use a bundler (webpack, Vite) that transpiles for browser support
- Legacy browsers: You'll need a bundler with polyfills regardless

After updating, test the compilation:

bash
npx tsc --noEmit
# or
npm run build
3Change module to a compatible format

If you must target ES3/ES5 (for legacy browser support), change the module system to a compatible format:

json
{
  "compilerOptions": {
    "module": "commonjs",    // ← Changed from esnext to commonjs
    "target": "es5",
    // ... other options
  }
}

Compatible module formats for ES3/ES5:
- commonjs: Node.js-style modules (require/exports)
- umd: Universal Module Definition (works in browsers and Node.js)
- amd: Asynchronous Module Definition (RequireJS)
- system: SystemJS module loader
- none: No module system (global scope)

Most common choice for ES5 targets:

json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "lib": ["es5", "dom"],
    "esModuleInterop": true,  // Important for CommonJS/ES module interop
    "allowSyntheticDefaultImports": true
  }
}

Note: With 'commonjs', you'll use require() syntax in output, but can still write import/export in TypeScript.

4Check extended configurations and overrides

If you're using tsconfig inheritance or multiple configuration files, check all relevant files:

json
// tsconfig.base.json (parent config)
{
  "compilerOptions": {
    "module": "esnext",
    "target": "es2015"
  }
}

// tsconfig.json (extends base)
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "target": "es5"  // ← Overrides to incompatible value!
  }
}

Common patterns to check:
1. Extends chains: Follow the inheritance chain
2. Project references: Check referenced project configurations
3. Build tools: Webpack, Vite, etc. may generate tsconfig
4. IDE settings: VS Code workspace settings can affect compilation

To see the final merged configuration:

bash
npx tsc --showConfig > tsconfig.effective.json
cat tsconfig.effective.json | grep -A2 -B2 "module|target"
5Verify with a minimal configuration

Create a minimal tsconfig.json to isolate the issue:

json
// tsconfig.minimal.json
{
  "compilerOptions": {
    "module": "esnext",
    "target": "es2015"
  },
  "include": ["src/**/*"]
}

Test with this minimal config:

bash
npx tsc --project tsconfig.minimal.json --noEmit

If this works, gradually add back your other compiler options to find which combination causes the error.

Common problematic options to check:
- moduleResolution: Should match your module system
- lib: Library files for your target
- esModuleInterop: Important for module compatibility
- allowSyntheticDefaultImports: Affects import behavior

6Update build tools and dependencies

Ensure your build tools support your TypeScript configuration:

bash
# Update TypeScript
npm install --save-dev typescript@latest

# Update related tools
npm install --save-dev @types/node ts-node

# For webpack users
npm install --save-dev ts-loader webpack webpack-cli

# For Vite users
npm install --save-dev vite @vitejs/plugin-react

Check package.json scripts:

json
{
  "scripts": {
    "build": "tsc",
    "dev": "tsc --watch",
    "check": "tsc --noEmit"
  }
}

Run a clean build:

bash
# Clear build artifacts
rm -rf dist build node_modules/.cache

# Reinstall dependencies
npm install

# Test compilation
npm run check

If using a framework (React, Angular, Vue), check their TypeScript requirements.

Advanced notes

### Understanding Module and Target Compatibility

TypeScript's module system transforms your import/export statements into different output formats based on the module setting. The target determines the JavaScript syntax features available.

Compatibility Matrix:
| Module System | ES3/ES5 | ES2015+ | Notes |
|---------------|---------|---------|-------|
| commonjs | ✓ | ✓ | Node.js default, requires bundler for browsers |
| amd | ✓ | ✓ | Async Module Definition (RequireJS) |
| umd | ✓ | ✓ | Universal (works everywhere) |
| system | ✓ | ✓ | SystemJS loader |
| es2015 | ✗ | ✓ | Native ES6 modules |
| es2020 | ✗ | ✓ | ES2020 module features |
| esnext | ✗ | ✓ | Latest proposals |

Why esnext requires ES2015+:
- esnext may use dynamic import() expressions (ES2020)
- May output export * as ns syntax (ES2020)
- Can use top-level await (ES2022)
- Future JavaScript module features

### Migration Strategies

From ES5 + CommonJS to ES2015 + ES Modules:
1. Update target: "es5" → "es2015"
2. Update module: "commonjs" → "esnext"
3. Add lib: ["es2015", "dom"]
4. Test with a bundler (webpack, Rollup)

Legacy Browser Support:
If you need ES5 for IE11 support:

json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "downlevelIteration": true,
    "lib": ["es5", "dom", "es2015.promise"]
  }
}

Then use Babel + webpack to transpile CommonJS to browser-compatible code.

### Module Resolution Differences

The moduleResolution option should align with your module:

- module: "commonjs" → moduleResolution: "node"
- module: "esnext" → moduleResolution: "node" (or "bundler" for modern tools)
- module: "es2015" → moduleResolution: "node"

Modern bundlers (Vite, esbuild) work best with:

json
{
  "module": "esnext",
  "moduleResolution": "bundler",
  "target": "es2020"
}

### Checking Your Environment

To see what JavaScript features your target supports:

bash
# Check Node.js version
node --version

# Check browser support via caniuse.com or MDN
# ES modules: https://caniuse.com/es6-module
# Dynamic import: https://caniuse.com/es6-module-dynamic-import

For Node.js projects, match target to your Node version:
- Node 12+: "target": "es2019"
- Node 14+: "target": "es2020"
- Node 16+: "target": "es2021"

### Debugging Configuration Issues

Use TypeScript's verbose output:

bash
npx tsc --extendedDiagnostics
npx tsc --listFiles
npx tsc --traceResolution

These show exactly how TypeScript interprets your configuration and files.

Frequently asked questions

What does "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'e" mean?
json. The module option controls how TypeScript generates module code (import/export statements), while the target option determines which ECMAScript version your code compiles to. The 'esnext' module system uses modern JavaScript module syntax that requires features only available in ES2015 (ES6) and later.
How do I fix "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'e"?
This TypeScript configuration error occurs when you try to use the modern 'esnext' module system with legacy JavaScript targets (ES3 or ES5). The esnext module format requires modern JavaScript features that aren't available in older ECMAScript versions. To fix this, either upgrade your target to ES2015+ or switch to a compatible module system like CommonJS.
What causes "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'e"?
Setting 'module' to 'esnext' while 'target' is 'es3' or 'es5' in tsconfig.json Inheriting tsconfig settings from a base configuration with incompatible values Using a template or starter project with mismatched compiler options
Is the "Option 'module' cannot be set to 'esnext' when 'target' is 'es3' or 'e" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading