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.
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.
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.
### 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
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript