This TypeScript error occurs when you try to import something that isn't exported from a module. The fix involves checking the export statements in the source file, verifying named vs default exports, and ensuring the import syntax matches the export style.
The "'X' is not exported from 'Y'" error (TS2305) appears when TypeScript cannot find the specified export in the module you're trying to import from. This happens because the import statement references something that doesn't exist in the module's exports. TypeScript's module system requires explicit exports - you can only import what has been exported. Common scenarios include: 1. **Missing export**: The item was never exported from the source file 2. **Wrong export type**: Using default import syntax for a named export (or vice versa) 3. **Typo in import name**: The imported name doesn't match the exported name 4. **Re-export issues**: The item is exported from a different file than expected 5. **Module structure changes**: The export was removed or renamed in a dependency update This error prevents compilation because TypeScript cannot verify type safety for imports that don't exist.
First, examine the source module to see what's exported:
// Check the module file (module.ts)
export const myFunction = () => {}; // Named export
export default class MyClass {}; // Default export
export { helperFunction }; // Re-export
export type { MyType }; // Type export
// Common mistakes:
// const notExported = () => {}; // NOT exported - can't import this
// function privateHelper() {} // NOT exported - can't import thisYou can also check exports programmatically:
# For npm packages, check the package.json exports field
cat node_modules/package-name/package.json | grep -A5 -B5 '"exports"'
# For local files, use TypeScript compiler to list exports
npx tsc --declaration --emitDeclarationOnly --outDir /tmp module.ts
cat /tmp/module.d.tsMatch your import syntax to the export style:
// MODULE exports:
// export const myFunction = () => {};
// export default class MyClass {};
// CORRECT imports:
import { myFunction } from './module'; // Named import for named export
import MyClass from './module'; // Default import for default export
import MyClass, { myFunction } from './module'; // Mixed import
// WRONG imports (cause TS2305):
import myFunction from './module'; // Default import for named export
import { MyClass } from './module'; // Named import for default export
import * as everything from './module'; // This works, but then use everything.myFunctionFor CommonJS modules using export =:
// MODULE (CommonJS style):
// export = { myFunction, MyClass };
// CORRECT import:
import * as module from './module'; // ES module import
// or with esModuleInterop:
import module from './module';
// Also ensure tsconfig.json has:
// {
// "compilerOptions": {
// "esModuleInterop": true,
// "allowSyntheticDefaultImports": true
// }
// }Module exports are case-sensitive. Verify exact spelling:
// MODULE exports:
export const formatDate = () => {};
export const FormatDate = () => {}; // Different name!
export const FORMATDATE = () => {}; // Another different name!
// WRONG imports:
import { formatdate } from './module'; // lowercase 'd'
import { Formatdate } from './module'; // missing capital 'D'
import { formatDate } from './module'; // ✓ Correct
import { FormatDate } from './module'; // ✓ Correct (different export)
import { FORMATDATE } from './module'; // ✓ Correct (different export)
// Use IDE features to avoid typos:
// 1. Let auto-complete suggest exports
// 2. Ctrl+Click/Cmd+Click on import to jump to definition
// 3. Use "Go to Definition" (F12) to see the actual exportFor packages, check the exact export names in documentation or type definitions:
# Check type definitions for a package
cat node_modules/@types/package-name/index.d.ts | head -50
# Or examine the package's main entry point
cat node_modules/package-name/dist/index.js | grep -i "export"When using barrel files (index.ts) or re-exports, ensure the chain is complete:
// File: src/components/Button.ts
export const Button = () => {}; // ✓ Exported
// File: src/components/index.ts (barrel file)
export { Button } from './Button'; // ✓ Re-exports Button
// export { Input } from './Input'; // ✗ Missing - Input won't be available
// File: src/index.ts
export * from './components'; // ✓ Exports everything from components
// CORRECT import:
import { Button } from './src'; // Works through re-export chain
// Debug broken chains:
// 1. Check each file in the chain exports the item
// 2. Verify no typos in re-export statements
// 3. Ensure circular dependencies aren't breaking exportsCommon re-export patterns:
// Re-export with rename
export { Button as MyButton } from './Button';
// Re-export type only
export type { Props } from './Button';
// Aggregate exports
export * from './components';
export * from './utils';
// Conditional exports (package.json)
// {
// "exports": {
// ".": {
// "import": "./dist/esm/index.js",
// "require": "./dist/cjs/index.js"
// },
// "./components": "./dist/esm/components/index.js"
// }
// }Package updates often change export structures:
# Check what changed in a package
npm view package-name versions # List all versions
npm view package-name@latest # Latest version info
# Compare your version with latest
npm list package-name # Your installed version
npm info package-name version # Latest available
# Check changelog for breaking changes
# Common breaking changes:
# - Renamed exports
# - Removed exports
# - Changed from default to named exports (or vice versa)
# - Added new required peer dependencies
# Update package (if appropriate)
npm install package-name@latest
# Or check migration guide
# Most packages have migration guides for major versionsIf you can't update, use type assertions or declaration merging:
// If export was removed but still exists at runtime
declare module "old-package" {
export const removedExport: any;
}
// Or use require for CommonJS modules
const { removedExport } = require("old-package");Ensure TypeScript can find and understand module exports:
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
// For modern packages
"module": "esnext",
// For type-only imports
"importsNotUsedAsValues": "preserve",
// Path mapping
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}Key settings:
- esModuleInterop: Allows default imports from CommonJS modules
- allowSyntheticDefaultImports: Suppresses errors for missing default exports
- moduleResolution: How TypeScript looks for module files
After changing config, restart TypeScript server:
# In VS Code: Ctrl/Cmd + Shift + P → "TypeScript: Restart TS Server"
# Or from command line:
npx tsc --build --clean### Understanding Module Systems
TypeScript supports multiple module systems:
ES Modules (ESM) - Modern standard:
// Export
export const named = "value";
export default function() {};
// Import
import { named } from './module';
import def from './module';CommonJS - Node.js legacy:
// Export
exports.named = "value";
module.exports = function() {};
// Import (with esModuleInterop)
import * as mod from './module';
import def from './module';UMD/AMD - Browser modules:
// Typically need type definitions
declare module "library" {
export const value: string;
}### Type-Only Imports
For types that shouldn't exist at runtime:
import type { User } from './types'; // Type-only import
import { type User, createUser } from './types'; // Mixed import
// These are removed from JavaScript output
// Use for: interfaces, types, const enums### Conditional Exports in package.json
Modern packages use conditional exports:
{
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js",
"types": "./dist/types/index.d.ts"
},
"./components": "./dist/esm/components/index.js"
}
}TypeScript 4.7+ supports this natively. Older versions may need typesVersions.
### Debugging Export Issues
1. Trace resolution:
npx tsc --traceResolution | grep "module-name"2. Check declaration files:
npx tsc --declaration --emitDeclarationOnly
cat dist/module.d.ts3. Use TypeScript compiler API:
import * as ts from "typescript";
const program = ts.createProgram(["module.ts"], {});
const sourceFile = program.getSourceFile("module.ts");
// Analyze exports programmatically### Circular Dependencies
Circular dependencies can break exports:
// File A.ts
import { b } from './B';
export const a = () => b();
// File B.ts
import { a } from './A'; // Circular!
export const b = () => a(); // May cause undefined exportsSolutions:
- Refactor to avoid circular dependencies
- Use dynamic imports import()
- Move shared code to third file
- Use dependency injection
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