How to fix Duplicate identifier 'X' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 203 views

This TypeScript compiler error occurs when the same identifier (variable, type, interface, or class) is declared multiple times in the same scope. The fix involves removing duplicate declarations, fixing conflicting type definitions, or converting script files to modules.

Quick fix

Fixes TS2300

// WRONG - duplicate interface declaration
interface User {
  name: string;
}

interface User {
  email: string;
}

// WRONG - duplicate variable
const API_URL = "https://api.example.com";
const API_URL = "https://staging.api.example.com";
  1. Check for duplicate declarations in your file
  2. Convert script files to modules
  3. Clean up conflicting type definition packages
  4. Use skipLibCheck to skip type definition checking
typescript — error
// WRONG - duplicate interface declaration
interface User {
name: string;
}
interface User {
email: string;
}
// WRONG - duplicate variable
const API_URL = "https://api.example.com";
const API_URL = "https://staging.api.example.com";
Duplicate identifier 'X'

What this error means

TypeScript enforces a strict rule that each identifier must be uniquely declared within its scope. When the TypeScript compiler encounters two or more declarations with the same name in the same scope, it emits error TS2300: Duplicate identifier. This error commonly appears in several scenarios: 1. **Accidental duplicate declarations**: You've declared the same interface, type, variable, or function twice in the same file 2. **Conflicting type definitions**: Multiple versions of @types packages or global type declarations conflict 3. **Script vs. module files**: Files without imports/exports are treated as global scripts, causing name collisions across your entire project 4. **Circular dependencies**: Two modules import from each other, creating duplicate type definitions The error is particularly common when working with declaration files (.d.ts), third-party type definitions from @types packages, or when migrating JavaScript code to TypeScript. Global scope pollution is a frequent culprit—any file without at least one import or export statement is considered a global script rather than a module.

Typical symptoms

  • TypeScript compilation fails with error TS2300: Duplicate identifier
  • Red squiggly lines under interface, type, or variable declarations in your IDE
  • Error message appears for identifiers that you've only declared once in your file
  • Conflicts appear after installing or updating @types packages (like @types/node)
  • Problems arise when multiple declaration files (.d.ts) are included in your project
  • Error occurs for common names like 'Buffer', 'process', 'Error', or 'Node'
  • Code works fine in one file but breaks when you add another file to the project

Common causes

  1. The same interface, type, class, or variable is declared twice in the same file
  2. Your file doesn't contain any import/export statements, making it a global script
  3. Multiple versions of the same @types package are installed in node_modules
  4. Conflicting type definitions from different libraries declare the same global name
  5. You're importing declaration files that define the same ambient types
  6. Circular module dependencies cause type definitions to be processed multiple times
  7. Legacy typings and modern @types packages both define the same types
  8. Two different files in your project declare the same global interface or type

How to fix "Duplicate identifier 'X'"

1Check for duplicate declarations in your file

First, search your file for the duplicate identifier. Look for multiple declarations:

typescript
// WRONG - duplicate interface declaration
interface User {
  name: string;
}

interface User {
  email: string;
}

// WRONG - duplicate variable
const API_URL = "https://api.example.com";
const API_URL = "https://staging.api.example.com";

Remove or merge the duplicates:

typescript
// CORRECT - single merged interface
interface User {
  name: string;
  email: string;
}

// CORRECT - single variable
const API_URL = "https://api.example.com";

For interfaces, TypeScript supports declaration merging when declarations are compatible, but it's clearer to have a single declaration.

2Convert script files to modules

If your file doesn't have any import or export statements, TypeScript treats it as a global script. This causes all declarations to pollute the global namespace and conflict with other files.

Add an export to convert it to a module:

typescript
// BEFORE - global script (problematic)
interface Result {
  success: boolean;
}

const calculate = () => {
  // ...
};

// AFTER - module (isolated scope)
interface Result {
  success: boolean;
}

const calculate = () => {
  // ...
};

// Add this line to make it a module
export {};

Now your declarations won't conflict with other files. The export {} is an empty export that signals to TypeScript that this is a module file.

3Clean up conflicting type definition packages

Check for duplicate or conflicting @types packages:

bash
# List all @types packages
npm ls @types

# Look for duplicates or multiple versions
npm ls @types/node

Common fixes:

bash
# Update to latest version
npm install --save-dev @types/node@latest

# Remove and reinstall all dependencies
rm -rf node_modules package-lock.json
npm install

# Deduplicate packages
npm dedupe

After cleaning up, restart your TypeScript server in VS Code:
- Press Ctrl+Shift+P (or Cmd+Shift+P on Mac)
- Type "TypeScript: Restart TS Server"
- Press Enter

4Use skipLibCheck to skip type definition checking

If the duplicates are coming from third-party type definitions that you can't control, enable skipLibCheck in your tsconfig.json:

json
{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

This tells TypeScript to skip type-checking for all declaration files (.d.ts), which can resolve conflicts from external packages. However, this is a workaround—it's better to fix the root cause if possible.

Note: This option improves compilation speed and works around third-party type issues, but you'll lose type-checking for those libraries.

5Resolve conflicts using import aliasing

If two modules export the same name and you need both, use import aliasing:

typescript
// BEFORE - conflict if both export 'Result'
import { Result } from "./api";
import { Result } from "./database"; // Error: Duplicate identifier 'Result'

// AFTER - use aliases
import { Result as ApiResult } from "./api";
import { Result as DbResult } from "./database";

// Now use them distinctly
const apiData: ApiResult = { success: true };
const dbData: DbResult = { rows: [] };

This pattern is especially useful when different libraries export types with common names like Config, Options, or Response.

6Exclude conflicting files in tsconfig.json

If specific declaration files are causing conflicts, exclude them from compilation:

json
{
  "compilerOptions": {
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": [
    "node_modules",
    "**/*.spec.ts",
    "legacy-typings/**/*"
  ]
}

Common exclusion patterns:
- Legacy typings folders
- Duplicate declaration files
- Test files that declare global test types
- Build output directories

Use the tsc --traceResolution command to see which files TypeScript is including and identify the source of duplicates:

bash
npx tsc --traceResolution | grep "duplicate-identifier-name"

Advanced notes

### Declaration Merging

TypeScript allows certain types of declarations to be merged. Interfaces can be merged if they're compatible:

typescript
// These will merge successfully
interface Window {
  customProperty: string;
}

interface Window {
  anotherProperty: number;
}

// Result: Window has both customProperty and anotherProperty

However, merging fails when declarations conflict:

typescript
// ERROR - conflicting property types
interface Config {
  timeout: string;
}

interface Config {
  timeout: number; // Error: Duplicate identifier with different type
}

### Module vs. Script Files

Understanding the difference is crucial:

- Module: Any file with import or export statements. Has its own scope.
- Script: Files without imports/exports. Declarations are global.

typescript
// script-file.ts (DANGEROUS - global scope)
const sharedValue = 100;

// another-script.ts (DANGEROUS - same global scope)
const sharedValue = 200; // Error: Duplicate identifier

Always prefer modules. Even if you have nothing to export, add export {}.

### Namespaces and Modules

Legacy TypeScript code may use namespaces. These can cause duplicate identifier errors when mixed with modern modules:

typescript
// Legacy namespace approach
namespace MyApp {
  export interface User {
    name: string;
  }
}

// Modern module approach
export interface User {
  name: string;
}

// If both exist, you get duplicate identifier errors

Migrate to ES modules instead of namespaces for new code.

### Circular Dependencies

Circular imports can cause duplicate identifier issues:

typescript
// a.ts
import { TypeB } from "./b";
export interface TypeA {
  b: TypeB;
}

// b.ts
import { TypeA } from "./a";
export interface TypeB {
  a: TypeA; // Circular reference
}

Fix by extracting shared types to a separate file:

typescript
// types.ts
export interface TypeA {
  b: TypeB;
}

export interface TypeB {
  a: TypeA;
}

// a.ts
import type { TypeA, TypeB } from "./types";

// b.ts
import type { TypeA, TypeB } from "./types";

### Global Type Augmentation

When augmenting global types (like adding properties to Window), declare them in a .d.ts file:

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

export {}; // Makes this a module

Without the export {}, the file is treated as a script, and multiple augmentation files will conflict.

Frequently asked questions

What does "TS2300" mean?
TypeScript enforces a strict rule that each identifier must be uniquely declared within its scope. When the TypeScript compiler encounters two or more declarations with the same name in the same scope, it emits error TS2300: Duplicate identifier. This error commonly appears in several scenarios: 1.
How do I fix "TS2300"?
This TypeScript compiler error occurs when the same identifier (variable, type, interface, or class) is declared multiple times in the same scope. The fix involves removing duplicate declarations, fixing conflicting type definitions, or converting script files to modules.
What causes "TS2300"?
The same interface, type, class, or variable is declared twice in the same file Your file doesn't contain any import/export statements, making it a global script Multiple versions of the same @types package are installed in node_modules
Is the "TS2300" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading