How to fix Module 'X' does not have a default export in TypeScript
This TypeScript error occurs when you try to import a module using default import syntax (import X from "module"), but the module only exports named exports. The fix involves changing your import syntax to use named imports or modifying the module to include a default export.
Quick fix
Fixes Module 'X' does not have a default export
// Check library documentation for correct import syntax
// Example: React only has named exports for components
import React from 'react'; // ❌ Wrong - React doesn't have default export
import { useState } from 'react'; // ✅ Correct - named import
// For your own modules, check the export statements:
// File: utils.ts
export function formatDate() { ... } // Named export
export const MAX_ITEMS = 100; // Named export
// No "export default ..." means no default export
// To import correctly:
import { formatDate, MAX_ITEMS } from './utils'; // ✅
import utils from './utils'; // ❌ No default export- Check the module's export structure
- Switch to named imports for modules without default exports
- Configure esModuleInterop for CommonJS modules
- Add a default export to your own modules
// Check library documentation for correct import syntax// Example: React only has named exports for componentsimport React from 'react'; // ❌ Wrong - React doesn't have default exportimport { useState } from 'react'; // ✅ Correct - named import// For your own modules, check the export statements:// File: utils.tsexport function formatDate() { ... } // Named exportexport const MAX_ITEMS = 100; // Named export// No "export default ..." means no default export// To import correctly:import { formatDate, MAX_ITEMS } from './utils'; // ✅import utils from './utils'; // ❌ No default exportModule 'X' does not have a default export
What this error means
The "Module 'X' does not have a default export" error occurs in TypeScript when you attempt to import a module using the default import syntax (`import something from 'module'`), but the module being imported doesn't have a default export. In JavaScript/TypeScript modules, there are two main types of exports: 1. **Default exports** - A single value exported as the "main" export of the module, imported with `import X from 'module'` 2. **Named exports** - Multiple values exported with specific names, imported with `import { X, Y } from 'module'` This error typically happens when: - You're importing a library that only provides named exports - You're importing your own module that uses named exports but you're trying to use default import syntax - The module uses CommonJS `module.exports = ...` syntax which TypeScript interprets differently based on configuration The error message helps you understand that the module structure doesn't match your import expectations, guiding you to use the correct import syntax.
Typical symptoms
- TypeScript compilation fails with "Module 'X' does not have a default export"
- IDE shows red underlines on import statements using default import syntax
- Error appears when trying to import from third-party libraries or your own modules
- Code works in JavaScript but fails in TypeScript due to stricter module checking
- Import works with named imports but fails with default imports
Common causes
- Using default import syntax for a module that only exports named exports
- Importing from a CommonJS module without proper TypeScript configuration
- Library documentation incorrectly suggests default import when only named exports exist
- Module uses mixed exports but you're trying to import the wrong way
- TypeScript configuration (esModuleInterop) affects how CommonJS modules are interpreted
How to fix "Module 'X' does not have a default export"
First, examine what the module actually exports. For third-party libraries, check their documentation or source code:
// Check library documentation for correct import syntax
// Example: React only has named exports for components
import React from 'react'; // ❌ Wrong - React doesn't have default export
import { useState } from 'react'; // ✅ Correct - named import
// For your own modules, check the export statements:
// File: utils.ts
export function formatDate() { ... } // Named export
export const MAX_ITEMS = 100; // Named export
// No "export default ..." means no default export
// To import correctly:
import { formatDate, MAX_ITEMS } from './utils'; // ✅
import utils from './utils'; // ❌ No default exportUse your IDE to inspect what exports are available. In VS Code, hover over the import or use "Go to Definition" (F12).
If the module only has named exports, use named import syntax:
// BEFORE (causing error):
import moment from 'moment'; // Error if moment doesn't have default export
// AFTER (using named import):
import { format, parseISO } from 'date-fns'; // date-fns uses named exports
// For libraries with a main default export AND named exports:
import React, { useState, useEffect } from 'react'; // React has both
// If you want to import everything as an object:
import * as utils from './utils'; // Then use utils.formatDate()Common libraries with only named exports:
- date-fns (date utility functions)
- lodash-es (ES module version of lodash)
- Many utility libraries that export multiple functions
For CommonJS modules (Node.js style: module.exports = ...), TypeScript needs special configuration:
// tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}With these settings, TypeScript allows default imports from CommonJS modules:
// CommonJS module (express.js):
// module.exports = express;
// With esModuleInterop: true
import express from 'express'; // ✅ Works
const app = express();
// Without esModuleInterop: true
import * as express from 'express'; // Alternative syntax
const app = express.default();esModuleInterop tells TypeScript to treat CommonJS modules as if they have a default export.
If you control the module and want to support default imports, add a default export:
// File: calculator.ts
// BEFORE (only named exports):
export function add(a: number, b: number) { return a + b; }
export function subtract(a: number, b: number) { return a - b; }
// AFTER (adding default export):
export function add(a: number, b: number) { return a + b; }
export function subtract(a: number, b: number) { return a - b; }
// Option 1: Export an object as default
export default { add, subtract };
// Option 2: Export a main function as default
export default function calculate(operation: string, a: number, b: number) {
// ...
}
// Now both imports work:
import calc from './calculator'; // Default import
import { add } from './calculator'; // Named importChoose the approach that makes sense for your API design.
If you're importing types/interfaces, use import type to avoid runtime issues:
// File: types.ts
export interface User { id: string; name: string; }
export type Status = 'active' | 'inactive';
// WRONG - trying to default import a type
import User from './types'; // Error: Module has no default export
// CORRECT - import type with named imports
import type { User, Status } from './types';
// For mixed imports (values and types):
import { getUser } from './api'; // Runtime function
import type { User } from './types'; // Type only
// TypeScript 5.0+ inline syntax:
import { getUser, type User } from './api';import type ensures you're only importing type information, which gets removed during compilation.
Modern packages use the exports field in package.json to define their module structure:
// package.json of a library
{
"name": "my-library",
"exports": {
".": {
"import": "./dist/esm/index.js", // ES modules
"require": "./dist/cjs/index.js", // CommonJS
"types": "./dist/types/index.d.ts"
},
"./utils": {
"import": "./dist/esm/utils.js",
"require": "./dist/cjs/utils.js",
"types": "./dist/types/utils.d.ts"
}
}
}If a package uses exports without a default export key, you may need to use named imports. Check the package's documentation or source to understand its export structure.
Advanced notes
### Understanding Module Systems
TypeScript interacts with different module systems:
ES Modules (ESM) - Modern JavaScript modules using import/export:
// Named exports
export const pi = 3.14;
export function calculate() { ... }
// Default export
export default function main() { ... }
// Mixed
export const config = { ... };
export default class App { ... }CommonJS - Node.js traditional modules using module.exports:
// Single export
module.exports = function() { ... };
// Multiple exports
module.exports = {
add: function(a, b) { return a + b; },
subtract: function(a, b) { return a - b; }
};
// Or
exports.add = function(a, b) { return a + b; };### TypeScript Configuration Flags
Key tsconfig.json options affecting module imports:
1. "esModuleInterop": true - Allows default imports from CommonJS modules
2. "allowSyntheticDefaultImports": true - Suppresses errors for missing default exports (doesn't affect runtime)
3. "moduleResolution": "node" or "node16" - Affects how modules are resolved
4. "module": "commonjs" vs "esnext" - Output module format
### Common Pitfalls
1. React 17+: import React from 'react' works because React provides both default and named exports, but many React libraries only use named exports.
2. Default re-exports:
// file: index.ts
export { default } from './Button'; // Re-exports default
export { ButtonProps } from './Button'; // Re-exports named
// Can import as:
import Button from './index'; // Gets the default from Button
import { ButtonProps } from './index'; // Gets named export3. Dynamic imports: Use different syntax:
// Static import (checked at compile time)
import { feature } from './module';
// Dynamic import (runtime)
const module = await import('./module');
const feature = module.feature; // Access named export
const defaultExport = module.default; // Access default if exists### Debugging Tools
1. Check what a module exports:
# For Node.js modules
node -e "console.log(Object.keys(require('module-name')))"
# Or inspect in TypeScript
npx tsc --noEmit --traceResolution2. VS Code: Hover over import to see available exports
3. Use TypeScript declaration files (.d.ts) to understand library structure
Frequently asked questions
- What does "Module 'X' does not have a default export" mean?
- The "Module 'X' does not have a default export" error occurs in TypeScript when you attempt to import a module using the default import syntax (import something from 'module'), but the module being imported doesn't have a default export. In JavaScript/TypeScript modules, there are two main types of exports: 1. Default exports - A single value exported as the "main" export of the module, imported with import X from 'module' 2.
- How do I fix "Module 'X' does not have a default export"?
- This TypeScript error occurs when you try to import a module using default import syntax (import X from "module"), but the module only exports named exports. The fix involves changing your import syntax to use named imports or modifying the module to include a default export.
- What causes "Module 'X' does not have a default export"?
- Using default import syntax for a module that only exports named exports Importing from a CommonJS module without proper TypeScript configuration Library documentation incorrectly suggests default import when only named exports exist
- Is the "Module 'X' does not have a default export" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖Typescriptlang.org - modules.html(Official Docs)
- 📖Typescriptlang.org - reference.html(Official Docs)
- 💬
- 🐙Github.com - 2242(GitHub)
- 🔗