How to fix Cannot export member 'X' in namespace in TypeScript
This TypeScript error occurs when you attempt to export a member directly from within a namespace declaration, usually when trying to re-export types or values from external modules. The fix involves using proper export syntax outside the namespace or restructuring your code to use ES6 modules instead of namespaces.
Quick fix
Fixes TS1363
namespace MyNamespace {
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;
}
export { MyNamespace };- Move exports outside the namespace declaration
- Convert from namespaces to ES6 modules
- If re-exporting, use proper syntax
- Avoid export assignment in namespaces
namespace MyNamespace {export type User = {id: string;name: string;};export const getUserName = (user: User) => user.name;}export { MyNamespace };Cannot export member 'X' in namespace
What this error means
The error "Cannot export member 'X' in namespace" occurs when TypeScript encounters export statements inside namespace declarations that it cannot handle. This typically happens in these scenarios: 1. You're trying to re-export a member from an external module from within a namespace 2. You're mixing namespace declarations with ES6 module export syntax 3. You're attempting to export namespace members that conflict with module exports 4. You're using export assignments within a namespace (which is not allowed) TypeScript namespaces are a legacy feature from before ES6 modules existed. They group related code under a single name but don't follow the same export rules as ES6 modules. When TypeScript encounters conflicting or unsupported export patterns in namespaces, it raises this error. The error is TypeScript's way of preventing ambiguous export patterns that could cause confusion about what's actually being exported from your module.
Typical symptoms
- TypeScript compilation fails with TS1363 error when declaring a namespace
- IDE shows 'Cannot export member' error on a specific identifier
- You're trying to re-export types or values from external modules inside a namespace
- Using export statements after export namespace declaration
- Error appears when mixing namespace and module export syntax
- The error points to a specific member name that you're trying to export
- Code compiles in JavaScript but TypeScript prevents it
- Migrating from namespace-based code to modules causes this error
Common causes
- Attempting to export a member that's already exported from the namespace scope
- Trying to re-export imported members directly from within a namespace
- Mixing ES6 module syntax (export) with namespace declarations
- Using export assignment (export =) inside a namespace, which is not allowed
- The member is being exported with conflicting access levels
- Circular export dependencies between namespaces and modules
- Namespace is trying to re-export external module members without proper syntax
- TypeScript version incompatibility with how namespaces are handled
How to fix "Cannot export member 'X' in namespace"
The most direct fix is to define your exports at the module level, outside of the namespace:
Before (causes error):
namespace MyNamespace {
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;
}
export { MyNamespace };After (fixed):
namespace MyNamespace {
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;
}
// Export the namespace itself, not individual members
export namespace MyNamespace {}Alternatively, export members directly at module level:
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;This approach clarifies what's being exported and aligns with ES6 module semantics.
The most modern solution is to replace namespaces with ES6 modules, which are the standard in TypeScript and JavaScript:
Before (namespace-based):
// users.ts
namespace Users {
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;
}
export { Users };After (ES6 modules):
// users.ts
export type User = {
id: string;
name: string;
};
export const getUserName = (user: User) => user.name;Consumer (before):
// app.ts
import { Users } from "./users";
const user: Users.User = { id: "1", name: "Alice" };Consumer (after):
// app.ts
import type { User } from "./users";
import { getUserName } from "./users";
const user: User = { id: "1", name: "Alice" };ES6 modules are:
- The standard across JavaScript ecosystem
- Better for tree-shaking and bundler optimization
- More compatible with modern tooling
- Easier to understand and maintain
- The recommended approach for new TypeScript code
When re-exporting members from external modules, use the correct export syntax:
Wrong (causes error):
// api-types.ts
import { User as ExternalUser } from "external-lib";
namespace API {
export type User = ExternalUser; // Error!
}
export { API };Correct:
// api-types.ts
export { User as APIUser } from "external-lib";
// Or if you want to wrap it:
import type { User as ExternalUser } from "external-lib";
export type User = ExternalUser;For re-exporting multiple items:
// index.ts
export * from "./users";
export * from "./products";
export * from "./orders";For selective re-exports:
// index.ts
export { User, createUser } from "./users";
export { Product, getProduct } from "./products";
export type { Order } from "./orders";Proper export syntax ensures TypeScript can correctly track what's being exported and to whom.
Never use export assignment (export =) inside a namespace - it's not allowed:
Wrong (causes error):
namespace MyNamespace {
const value = "test";
export = value; // ERROR: TS1363
}Correct (use export statements instead):
namespace MyNamespace {
export const value = "test";
}
export { MyNamespace };If you need default export, use at module level:
// utils.ts
const utilities = {
value: "test",
getName: () => "Utils",
};
export default utilities;CommonJS-style export:
If you must use CommonJS style (which is legacy), do it outside namespace:
namespace MyNamespace {
export const value = "test";
}
export = MyNamespace;Export assignments should only appear at the module level, not inside namespace declarations.
Ensure that member names aren't conflicting with existing exports:
Problem: Duplicate exports:
namespace API {
export type Response = { status: number };
}
export type Response = string; // Conflict!
export { API };Solution: Use explicit naming:
namespace API {
export type APIResponse = { status: number };
}
export type Response = string;
export { API };
// Consumers can now distinguish:
// type APIResponse = API.APIResponse;
// type MyResponse = Response;Or use separate files:
// api/types.ts
export type Response = { status: number };
// app/types.ts
export type Response = string;Check for circular dependencies:
# Use TypeScript compiler to check dependencies
tsc --listFilesOnly
# Look for files importing each otherClear naming and proper file organization prevent conflicts.
Ensure your tsconfig.json supports proper module syntax:
Check your tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"strict": true,
"esModuleInterop": true
}
}Key settings for avoiding namespace issues:
{
"compilerOptions": {
// Use modern module syntax
"module": "ESNext",
// Enable proper Node.js resolution
"moduleResolution": "node",
// Allow importing CommonJS modules
"esModuleInterop": true,
// Generate .d.ts files for libraries
"declaration": true,
// Strict null checks catch more issues
"strict": true
}
}For library authors:
{
"compilerOptions": {
"outDir": "./dist",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"module": "ESNext"
}
}Proper configuration helps TypeScript correctly understand your export patterns and report errors accurately.
If you're working with legacy code using namespaces, refactor systematically:
Step 1: Identify all namespace exports
// Find all namespace declarations
grep -r "namespace " src/ --include="*.ts"
grep -r "export namespace" src/ --include="*.ts"Step 2: Convert one namespace at a time to modules
// Before: namespace with nested members
namespace Utils {
namespace String {
export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
}
namespace Array {
export const unique = <T>(arr: T[]) => [...new Set(arr)];
}
}// After: proper file structure
// utils/string.ts
export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
// utils/array.ts
export const unique = <T>(arr: T[]) => [...new Set(arr)];
// utils/index.ts
export * as String from "./string";
export * as Array from "./array";Step 3: Update imports in consuming code
// Before
import { Utils } from "./utils";
Utils.String.capitalize("hello");
// After
import { String } from "./utils";
String.capitalize("hello");Step 4: Run tests and verify all exports work
npm test
npm run buildSystematic refactoring prevents breaking changes while modernizing your codebase.
Advanced notes
Namespaces vs Modules: A Historical Context
TypeScript namespaces were created before ES6 modules existed, to provide a way to organize code and avoid global namespace pollution. However, ES6 modules (the standard since 2015) provide a superior solution:
- Namespaces: Use dot notation (namespace.member), require import statements at the file level, are less compatible with build tools
- Modules: Use declarative syntax, allow selective imports, work seamlessly with tree-shaking and bundlers
Why You Shouldn't Use Namespaces (Unless Supporting Legacy Code)
The TypeScript handbook itself recommends against namespaces for new code. They:
1. Add cognitive overhead (extra nesting levels)
2. Complicate bundler optimization
3. Create ambiguity about what's exported from a file
4. Are incompatible with modern build tools and package standards
5. Make circular dependency detection harder
Export Patterns and Their Rules
Named exports (recommended):
// At module level only
export const feature1 = () => {};
export type Config = { /* ... */ };
export class Service {}Namespace re-export:
// Define at module level, not inside namespace
namespace API {
export const endpoint = "/api";
}
export { API };Barrel exports (re-exporting from one file):
// index.ts
export * from "./users";
export * from "./products";
export { default as logger } from "./logger";Default + named exports:
export default function createApp() {}
export const config = { debug: true };Export assignment (CommonJS-style, legacy):
// Only at module level
export = MyClass;Common Mistakes with Namespaces
1. Attempting to export from within namespace:
namespace Foo {
export const x = 1;
}
export { Foo }; // OK - exports the namespace
export Foo.x; // ERROR - can't export member of namespace2. Mixing export patterns:
export namespace API {} // Fine
export const apiKey = "secret"; // Fine
export type Request = {}; // Fine
// But avoid:
namespace API {
export = someValue; // ERROR
}3. Expecting namespace members to be top-level exports:
namespace Utils {
export const helper = () => {};
}
// This doesn't work:
import { helper } from "./utils"; // ERROR
// Must be:
import { Utils } from "./utils";
Utils.helper();
// Or convert to modules:
// utils.ts has: export const helper = () => {};
import { helper } from "./utils"; // OKMigration Strategy for Large Codebases
If you have a large namespace-based codebase:
1. Phase 1: Enable "skipLibCheck": true and "allowSyntheticDefaultImports": true in tsconfig to reduce errors
2. Phase 2: Identify critical namespaces and convert them first
3. Phase 3: Update imports gradually, file by file
4. Phase 4: Run extensive tests to ensure no functionality breaks
5. Phase 5: Remove namespace declarations entirely
Use TypeScript's language server to assist with automated refactoring:
- Use "Rename Symbol" to update all references
- Use "Organize Imports" to clean up after refactoring
- Use "Go to References" to find all usages
Debugging Namespace Export Issues
When stuck, use these debugging techniques:
// Check what TypeScript thinks is exported
const check: typeof MyNamespace = {};
// Look at generated .d.ts files
tsc --declaration --declarationDir ./dist
// Enable verbose logging
tsc --diagnostics --prettyReview the generated type definitions to see what TypeScript actually exported - this often reveals the issue.
Frequently asked questions
- What does "TS1363" mean?
- The error "Cannot export member 'X' in namespace" occurs when TypeScript encounters export statements inside namespace declarations that it cannot handle. This typically happens in these scenarios: 1. You're trying to re-export a member from an external module from within a namespace 2.
- How do I fix "TS1363"?
- This TypeScript error occurs when you attempt to export a member directly from within a namespace declaration, usually when trying to re-export types or values from external modules. The fix involves using proper export syntax outside the namespace or restructuring your code to use ES6 modules instead of namespaces.
- What causes "TS1363"?
- Attempting to export a member that's already exported from the namespace scope Trying to re-export imported members directly from within a namespace Mixing ES6 module syntax (export) with namespace declarations
- Is the "TS1363" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.