How to fix Export declaration conflicts with exported declaration of 'X' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 124 views

This TypeScript error occurs when you attempt to export the same symbol name multiple times from a module, or when using re-export statements in module augmentation. The fix involves using direct export declarations instead of re-export syntax, or renaming conflicting exports.

Quick fix

Fixes TS2484

// WRONG - This can cause TS2484 in module augmentation
class MyClass {
  // ...
}
export { MyClass };

// CORRECT - Use inline export declaration
export class MyClass {
  // ...
}
  1. Use inline export declarations instead of re-export syntax
  2. Check for duplicate export statements in the same file
  3. Rename conflicting exports when merging modules
  4. Fix module augmentation conflicts
typescript — error
// WRONG - This can cause TS2484 in module augmentation
class MyClass {
// ...
}
export { MyClass };
// CORRECT - Use inline export declaration
export class MyClass {
// ...
}
Export declaration conflicts with exported declaration of 'X'

What this error means

The "Export declaration conflicts with exported declaration" error (TS2484) appears when TypeScript detects that you're trying to export the same symbol name more than once from a module. This typically happens in one of two scenarios: either you have genuinely duplicate exports (exporting the same variable/type/class twice), or you're using re-export syntax (`export { SymbolName }`) in a context where it conflicts with another export. TypeScript enforces that each exported symbol must have a unique name within a module's export namespace. When the compiler encounters two exports with identical names, it cannot determine which one should be exposed to consumers of the module, resulting in this error. The error is particularly common when: 1. **Re-export statements in module augmentation**: Using `export { SymbolName }` syntax instead of inline exports when augmenting modules 2. **Combined declaration files**: Multiple modules exporting the same symbol get merged into a single index.d.ts file 3. **Declaration merging conflicts**: Attempting to merge declarations incorrectly across files 4. **Accidental duplicate exports**: The same variable is exported both inline and in an export block

Typical symptoms

  • Compilation fails with 'Export declaration conflicts with exported declaration of' followed by the symbol name
  • Error code TS2484 appears in compiler output
  • Type declaration files (.d.ts) show duplicate export errors
  • Module augmentation fails when using export clauses
  • Error occurs in combined/bundled declaration files but not in source files
  • IDE shows red underlines on export statements even though logic seems correct

Common causes

  1. Using re-export syntax (export { X }) instead of inline exports in module augmentation
  2. The same symbol is exported twice in the same file (once inline, once in export block)
  3. Multiple declaration files export the same global symbol (e.g., 'Buffer' from different @types packages)
  4. Conflicting type definitions when bundling multiple modules into a single .d.ts file
  5. Attempting to export both a type and value with the same name from different sources
  6. Module augmentation with export clauses conflicts with existing module exports
  7. Incorrect declaration merging when extending third-party library types

How to fix "Export declaration conflicts with exported declaration of 'X'"

1Use inline export declarations instead of re-export syntax

The most common fix is to replace re-export statements with inline export declarations:

typescript
// WRONG - This can cause TS2484 in module augmentation
class MyClass {
  // ...
}
export { MyClass };

// CORRECT - Use inline export declaration
export class MyClass {
  // ...
}

For functions and variables:

typescript
// WRONG
function helperFunction() {
  return "data";
}
export { helperFunction };

// CORRECT
export function helperFunction() {
  return "data";
}

This is especially important when augmenting modules or working with declaration files.

2Check for duplicate export statements in the same file

Ensure you're not accidentally exporting the same symbol twice:

typescript
// WRONG - Duplicate exports
export const API_KEY = "abc123";

// Later in the same file...
export { API_KEY };  // Error: conflicts with earlier export

// CORRECT - Export once only
export const API_KEY = "abc123";

Search your file for all occurrences of the symbol name:

bash
# Check for duplicate exports
grep "export.*SymbolName" src/yourfile.ts

Remove any duplicate export statements, keeping only one export declaration.

3Rename conflicting exports when merging modules

If multiple modules need to export similar functionality, use unique names or namespaces:

typescript
// module-a.ts
export interface Config {
  timeout: number;
}

// module-b.ts - WRONG: same name causes conflict in combined .d.ts
export interface Config {
  retries: number;
}

// module-b.ts - CORRECT: use unique name or namespace
export interface NetworkConfig {
  retries: number;
}

// Or use namespaces to avoid conflicts
export namespace ModuleB {
  export interface Config {
    retries: number;
  }
}

For re-exports with aliasing:

typescript
// index.ts
export { Config as DatabaseConfig } from "./db/config";
export { Config as APIConfig } from "./api/config";
4Fix module augmentation conflicts

When augmenting external modules, ensure you're not creating export conflicts:

typescript
// WRONG - Can cause conflicts with export clause
declare module "express" {
  interface Request {
    user?: User;
  }
  export { Request };  // This can conflict
}

// CORRECT - Let declaration merging handle it
declare module "express" {
  interface Request {
    user?: User;
  }
}

// CORRECT - Use inline export in augmentation
declare module "my-lib" {
  export interface NewFeature {
    enabled: boolean;
  }
}

For module augmentation, prefer declaration merging over explicit export statements.

5Enable skipLibCheck to bypass third-party conflicts

If the conflict is in node_modules type definitions (e.g., multiple packages defining 'Buffer'), enable skipLibCheck:

json
// tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

This tells TypeScript to skip type checking of declaration files, which can resolve conflicts from incompatible @types packages:

bash
# Example: Conflicting Buffer definitions
# from @types/node and another package
npm install @types/node@latest --save-dev

Warning: This is a workaround, not a proper fix. It may hide legitimate type errors in your dependencies. Use only when dealing with third-party conflicts you cannot control.

6Resolve duplicate type definition packages

Check if you have multiple versions of the same @types package:

bash
# List all installed type packages
npm list | grep @types

# Check for duplicate versions
npm ls @types/node

# Remove duplicates by ensuring compatible versions
npm dedupe

# Or explicitly install a single version
npm install @types/node@^20.0.0 --save-dev --save-exact

For monorepos or complex dependency trees:

bash
# Check which packages are pulling in conflicting types
npm ls @types/packagename

# Use resolutions field in package.json (npm 8.3+)
{
  "overrides": {
    "@types/node": "^20.0.0"
  }
}

Clean install after resolving version conflicts:

bash
rm -rf node_modules package-lock.json
npm install

Advanced notes

### Module Augmentation Best Practices

When augmenting third-party modules, TypeScript's declaration merging has specific rules about exports:

typescript
// Good pattern for module augmentation
declare module "express-serve-static-core" {
  interface Request {
    user?: User;
  }
}

// Augmenting with new exports
declare module "my-library" {
  export interface ExtendedConfig extends Config {
    newOption: boolean;
  }

  export function newHelperFunction(): void;
}

Avoid using export clauses (export { ... }) in module augmentation. Let TypeScript's declaration merging handle the exports automatically.

### Understanding Export Syntax Differences

TypeScript has two main export syntaxes with different behaviors:

Named exports (inline):

typescript
export class MyClass {}
export interface MyInterface {}
export function myFunction() {}

Re-export syntax:

typescript
class MyClass {}
interface MyInterface {}
function myFunction() {}

export { MyClass, MyInterface, myFunction };

While both work in regular modules, re-export syntax can cause TS2484 when:
- Used in module augmentation
- Combined with declaration merging
- Bundled into declaration files

Recommendation: Use inline exports by default, especially in .d.ts files and module augmentations.

### Declaration File Bundling Conflicts

When building a library that bundles multiple source files into a single .d.ts file, conflicts can arise:

typescript
// src/moduleA.ts
export interface Config {
  optionA: boolean;
}

// src/moduleB.ts
export interface Config {  // Conflict when bundled
  optionB: boolean;
}

Solutions:

1. Namespace isolation:

typescript
// src/moduleA.ts
export namespace ModuleA {
  export interface Config {
    optionA: boolean;
  }
}

2. Unique naming:

typescript
// src/moduleA.ts
export interface ModuleAConfig {
  optionA: boolean;
}

3. Proper module exports in bundler config (rollup-plugin-dts, api-extractor):

javascript
// Ensure each module maintains its own scope
export default {
  input: {
    moduleA: 'src/moduleA.ts',
    moduleB: 'src/moduleB.ts'
  },
  output: {
    dir: 'dist',
    format: 'es'
  }
}

### Debugging Export Conflicts

Find all exports in your codebase:

bash
# Search for all export statements
grep -rn "export.*SymbolName" src/

# Find duplicate declarations
grep -rn "^export (class|interface|type|const|function) SymbolName" src/

Generate declaration files to see bundled output:

bash
npx tsc --declaration --emitDeclarationOnly

# Check generated .d.ts files for conflicts
cat dist/index.d.ts | grep "export.*SymbolName"

### Type vs Value Export Conflicts

TypeScript distinguishes between type exports and value exports. Conflicts occur when you export both:

typescript
// This is fine - same name, same entity
export interface User {
  name: string;
}

// This causes conflict - User is both type and value
export const User = {
  create: () => ({ name: "" })
};

// Solution: Use different names
export interface UserType {
  name: string;
}

export const UserFactory = {
  create: (): UserType => ({ name: "" })
};

// Or use namespace for grouping
export namespace User {
  export interface Type {
    name: string;
  }

  export const create = (): Type => ({ name: "" });
}

### Global Augmentation Conflicts

When augmenting global scope, ensure no conflicts with existing globals:

typescript
// global.d.ts
declare global {
  interface Window {
    customProperty: string;
  }

  // WRONG - conflicts with built-in Buffer
  interface Buffer {
    customMethod(): void;
  }

  // CORRECT - extend existing Buffer instead
  // (requires @types/node)
  namespace NodeJS {
    interface Buffer {
      customMethod(): void;
    }
  }
}

export {};  // Make this a module

Frequently asked questions

What does "TS2484" mean?
The "Export declaration conflicts with exported declaration" error (TS2484) appears when TypeScript detects that you're trying to export the same symbol name more than once from a module. This typically happens in one of two scenarios: either you have genuinely duplicate exports (exporting the same variable/type/class twice), or you're using re-export syntax (export { SymbolName }) in a context where it conflicts with another export. TypeScript enforces that each exported symbol must have a unique name within a module's export namespace.
How do I fix "TS2484"?
This TypeScript error occurs when you attempt to export the same symbol name multiple times from a module, or when using re-export statements in module augmentation. The fix involves using direct export declarations instead of re-export syntax, or renaming conflicting exports.
What causes "TS2484"?
Using re-export syntax (export { X }) instead of inline exports in module augmentation The same symbol is exported twice in the same file (once inline, once in export block) Multiple declaration files export the same global symbol (e.g., 'Buffer' from different @types packages)
Is the "TS2484" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading