This TypeScript error occurs when trying to declare a namespace in a file that TypeScript doesn't recognize as a module. Namespaces require module context, which can be enabled by adding export statements, using ES modules, or configuring TypeScript appropriately.
Fixes Namespace cannot be declared in non-module context
// Add this to make the file a module
export {};
// Now you can declare namespaces
namespace MyNamespace {
export function doSomething() {
console.log("Hello from namespace");
}
}// Add this to make the file a moduleexport {};// Now you can declare namespacesnamespace MyNamespace {export function doSomething() {console.log("Hello from namespace");}}Namespace cannot be declared in non-module context
TypeScript namespaces are a way to organize code and prevent naming conflicts by grouping related functionality. However, namespaces can only be declared in module contexts - files that TypeScript recognizes as modules. A file becomes a module when it contains at least one import or export statement, or when using ES module syntax. This error prevents namespace declarations in script files (non-modules) where all code is in the global scope.
The simplest fix is to add any export statement to your file. This tells TypeScript the file is a module, allowing namespace declarations.
// Add this to make the file a module
export {};
// Now you can declare namespaces
namespace MyNamespace {
export function doSomething() {
console.log("Hello from namespace");
}
}If you're using ES modules, ensure you have proper import/export statements:
// Import something to make it a module
import { something } from "./other-module";
// Or export something
export const myConstant = 42;
namespace MyNamespace {
export function doSomething() {
console.log("Working with", something);
}
}Ensure your TypeScript configuration is set up correctly for modules:
{
"compilerOptions": {
"module": "commonjs", // or "es2015", "esnext", etc.
"target": "es2015",
// Other options...
}
}Common module settings:
- "commonjs": For Node.js environments
- "es2015" / "esnext": For modern JavaScript
- "amd": For RequireJS/AMD modules
- "umd": Universal module definition
Modern TypeScript/JavaScript favors ES modules over namespaces. Consider converting namespace code to module exports:
// Instead of:
namespace Utilities {
export function formatDate(date: Date): string {
return date.toISOString();
}
}
// Use:
export function formatDate(date: Date): string {
return date.toISOString();
}
// Or group in an object:
export const Utilities = {
formatDate(date: Date): string {
return date.toISOString();
}
};If you need to augment global types in a non-module context, use declare global instead of namespaces:
// In a .d.ts file or file without imports/exports
declare global {
interface Window {
myCustomProperty: string;
}
}
// This works in non-module contexts
// while namespaces would failTypeScript has two file modes: scripts and modules. Scripts are files without imports/exports where all code is in global scope. Modules are files with imports/exports that have their own scope. Namespaces are only allowed in modules because they create their own scope. The isolatedModules compiler flag can affect this behavior - when enabled, all files must be modules. For legacy codebases, you might need to add export {} to many files to make them modules. Note that namespaces are somewhat deprecated in favor of ES modules, but are still useful for organizing large codebases or creating declaration files.