How to fix Re-exports require an export specifier in TypeScript
This TypeScript error occurs when you try to re-export everything from a module using 'export * from' syntax without specifying what to export. The fix involves using named exports, namespace exports, or adjusting your module structure to properly re-export the desired content.
Quick fix
Fixes TS1205
// WRONG - missing export specifier
export * from './utils';
// CORRECT - export everything as a namespace
export * as utils from './utils';
// CORRECT - export specific named exports
export { functionA, functionB } from './utils';
// CORRECT - export default
export { default } from './utils';
// CORRECT - export everything (valid in some contexts)
export * from './utils/*'; // Note: this exports from multiple files- Fix invalid 'export * from' syntax
- Create proper barrel files with named exports
- Handle CommonJS to ES module migration
- Configure TypeScript for proper module resolution
// WRONG - missing export specifierexport * from './utils';// CORRECT - export everything as a namespaceexport * as utils from './utils';// CORRECT - export specific named exportsexport { functionA, functionB } from './utils';// CORRECT - export defaultexport { default } from './utils';// CORRECT - export everything (valid in some contexts)export * from './utils/*'; // Note: this exports from multiple filesRe-exports require an export specifier
What this error means
The "Re-exports require an export specifier" error (TS1205) appears when TypeScript encounters invalid re-export syntax. Re-exports allow you to export items from another module as if they were defined in the current module, but they must follow specific syntax rules. In TypeScript/ES modules, you can re-export in several ways: 1. **Named re-exports**: `export { name } from './module'` 2. **Namespace re-exports**: `export * as namespace from './module'` 3. **Default re-exports**: `export { default } from './module'` The error typically occurs when you try to use `export * from './module'` without any specifier, which is invalid syntax. You need to either export specific named exports or use the namespace export syntax. This error is common when refactoring code, creating barrel files (index.ts files that export from multiple modules), or when migrating from CommonJS to ES modules.
Typical symptoms
- Compilation fails with 'Re-exports require an export specifier' error
- Error code TS1205 appears in compiler output
- IDE shows red underlines on export statements
- Build process fails when using barrel files or re-export patterns
- Error occurs specifically on lines with 'export * from' syntax
- Module bundlers (webpack, Vite) may also report the error
Common causes
- Using 'export * from' without any export specifier (invalid syntax)
- Attempting to re-export everything from a module without proper syntax
- Confusion between ES module re-export syntax and CommonJS patterns
- Missing or incorrect TypeScript configuration for module resolution
- Trying to create a barrel file with incorrect export syntax
- Mixing ES module and CommonJS syntax in the same project
- Using outdated TypeScript version that doesn't support certain re-export patterns
How to fix "Re-exports require an export specifier"
The most common cause is using export * from without proper syntax. Here's how to fix it:
// WRONG - missing export specifier
export * from './utils';
// CORRECT - export everything as a namespace
export * as utils from './utils';
// CORRECT - export specific named exports
export { functionA, functionB } from './utils';
// CORRECT - export default
export { default } from './utils';
// CORRECT - export everything (valid in some contexts)
export * from './utils/*'; // Note: this exports from multiple filesIf you want to export everything from a module, you have two options:
1. Use namespace export: export * as moduleName from './module'
2. Export specific items: export { item1, item2, default } from './module'
After fixing the syntax, compile again:
npx tsc
# or
npm run buildBarrel files (index.ts files that export from multiple modules) need proper syntax:
// WRONG barrel file
export * from './button';
export * from './input';
export * from './form';
// CORRECT barrel file - export specific items
export { Button, ButtonProps } from './button';
export { Input, InputProps } from './input';
export { Form, FormProps } from './form';
// CORRECT barrel file - namespace exports
export * as Button from './button';
export * as Input from './input';
export * as Form from './form';
// CORRECT barrel file - mixed approach
export { Button, ButtonProps } from './button';
export * as Input from './input';
export { default as Form } from './form';Best practices for barrel files:
- Export only what's needed (avoid export *)
- Use consistent patterns across your codebase
- Consider using export type for type-only exports
- Document what each barrel file exports
Example of a well-structured barrel file:
// src/components/index.ts
export { Button, type ButtonProps } from './Button';
export { Input, type InputProps } from './Input';
export { Card, type CardProps } from './Card';
export { default as Modal } from './Modal';If you're migrating from CommonJS to ES modules, re-exports work differently:
// CommonJS style (WRONG in ES modules)
module.exports = require('./utils');
// ES module equivalent (CORRECT)
export * from './utils'; // Still needs fixing!
export * as utils from './utils'; // Better
// CommonJS re-export pattern
exports.foo = require('./foo').foo;
exports.bar = require('./bar').bar;
// ES module equivalent
export { foo } from './foo';
export { bar } from './bar';
// For default exports
const utils = require('./utils');
module.exports = utils;
// ES module equivalent
export { default } from './utils';
// or
import utils from './utils';
export default utils;Update your package.json to specify module type:
{
"type": "module"
}And update tsconfig.json:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "node16"
}
}Ensure your tsconfig.json supports the re-export patterns you're using:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "node16",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"resolveJsonModule": true,
// For namespace exports
"preserveSymlinks": true,
// For better re-export support
"verbatimModuleSyntax": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}Key settings:
- module: Use ESNext for modern ES modules
- moduleResolution: node16 or bundler for proper ES module support
- allowSyntheticDefaultImports: Helps with default exports
- esModuleInterop: Improves compatibility with CommonJS modules
- verbatimModuleSyntax: Ensures imports/exports are preserved as written
After updating tsconfig.json, restart your TypeScript server:
# In VS Code: Ctrl/Cmd + Shift + P, then "TypeScript: Restart TS Server"If you're only exporting types, use type-only exports to avoid runtime issues:
// WRONG - exports both value and type
export { User, type UserProps } from './types';
// BETTER - separates type and value exports
export { User } from './types';
export type { UserProps } from './types';
// CORRECT - type-only re-export
export type { UserProps } from './types';
// For multiple type exports
export type { UserProps, PostProps, CommentProps } from './types';
// Namespace for types
export type * as Types from './types';Type-only exports are removed during compilation, so they don't affect the runtime code. This is especially important for:
1. Library authors: Consumers only get the types they need
2. Tree-shaking: Bundlers can remove unused type exports
3. Circular dependencies: Type-only imports don't create runtime dependencies
Check if you need import type instead of regular imports:
// Regular import (includes runtime code)
import { User } from './types';
// Type-only import (removed during compilation)
import type { UserProps } from './types';Some re-export patterns require newer TypeScript versions:
# Check current TypeScript version
npx tsc --version
# Update TypeScript
npm install typescript@latest --save-dev
# Or update to a specific version
npm install typescript@5.0.0 --save-devNewer TypeScript versions support:
- export type * syntax (TypeScript 3.8+)
- export * as ns syntax (TypeScript 3.8+)
- Better ES module/CJS interop
- Improved error messages for re-exports
Check your package.json for compatibility:
{
"devDependencies": {
"typescript": "^5.0.0"
},
"engines": {
"node": ">=16.0.0"
}
}After updating, clear any cached files:
# Remove compiled files
rm -rf dist build
# Clear TypeScript cache
rm -rf node_modules/.cache
# Reinstall if needed
npm install
# Compile fresh
npx tsc --build --clean
npx tscAdvanced notes
### Understanding Re-export Syntax Variations
TypeScript/JavaScript has several re-export patterns with different behaviors:
1. Named re-exports: export { a, b } from './module'
- Re-exports specific named exports
- Can rename: export { a as alpha, b as beta } from './module'
- Type-only: export type { T } from './module'
2. Namespace re-exports: export * as ns from './module' (TS 3.8+)
- Exports everything under a namespace
- Useful for organizing related exports
- Consumers import: import { ns } from './file'
3. Aggregating re-exports: export * from './module'
- Actually valid in some contexts!
- Exports all named exports (except default)
- Cannot be used at module top-level without specifier
- Works in specific patterns: export * from './folder/*'
4. Default re-exports: export { default } from './module'
- Re-exports the default export
- Alternative: import x from './module'; export default x;
### Barrel File Design Patterns
Well-designed barrel files improve developer experience:
// Pattern 1: Flat exports (simple)
export { Button } from './Button';
export { Input } from './Input';
export { Card } from './Card';
// Pattern 2: Namespaced (organized)
export * as Buttons from './buttons';
export * as Forms from './forms';
export * as Layout from './layout';
// Pattern 3: Mixed with utilities
export { Button, Input, Card } from './components';
export { formatDate, parseCurrency } from './utils';
export type { User, Product } from './types';
// Pattern 4: Lazy exports (for code splitting)
export { lazy } from 'react';
export const LazyButton = lazy(() => import('./Button'));### Module Resolution and Path Aliases
When using path aliases in tsconfig.json, re-exports need special handling:
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@components/*": ["components/*"],
"@utils/*": ["utils/*"]
}
}
}Re-exports with aliases:
// Works in TypeScript
export { Button } from '@components/Button';
// May need runtime resolution
// Use a bundler (webpack, Vite) or module-alias package### Circular Dependencies and Re-exports
Re-exports can create circular dependencies. TypeScript handles these better than runtime:
// fileA.ts
export { b } from './fileB'; // Re-export from B
// fileB.ts
export { a } from './fileA'; // Re-export from A (circular!)
// Better: Use type-only imports/exports
export type { AType } from './fileA';### Tooling Support
Different tools handle re-exports differently:
- Bundlers (webpack, Rollup): May tree-shake unused re-exports
- Test runners (Jest): May need moduleNameMapper for path aliases
- IDEs (VS Code): Use "Go to Definition" on re-exports to find source
- Linters (ESLint): import/no-useless-path-segments rule checks re-exports
### Debugging Re-export Issues
Use TypeScript's compiler hints:
# Show module resolution
npx tsc --traceResolution
# Show all diagnostics
npx tsc --extendedDiagnostics
# Show import/export relationships
npx tsc --listFilesCheck what's actually being exported:
# For Node.js modules
node -e "console.log(Object.keys(require('./dist/index.js')))"
# For ES modules (Node.js with --experimental-modules)
node --loader ts-node/esm ./test-imports.mjsFrequently asked questions
- What does "TS1205" mean?
- The "Re-exports require an export specifier" error (TS1205) appears when TypeScript encounters invalid re-export syntax. Re-exports allow you to export items from another module as if they were defined in the current module, but they must follow specific syntax rules. In TypeScript/ES modules, you can re-export in several ways: 1.
- How do I fix "TS1205"?
- This TypeScript error occurs when you try to re-export everything from a module using 'export * from' syntax without specifying what to export. The fix involves using named exports, namespace exports, or adjusting your module structure to properly re-export the desired content.
- What causes "TS1205"?
- Using 'export * from' without any export specifier (invalid syntax) Attempting to re-export everything from a module without proper syntax Confusion between ES module re-export syntax and CommonJS patterns
- Is the "TS1205" 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
- 📖TypeScript Handbook - Re-exports(Official Docs)
- 📖TypeScript Handbook - Module Reference(Official Docs)
- 📖TypeScript TSConfig - verbatimModuleSyntax(Official Docs)
- 🐙