What is a Namespace in TypeScript?
Learn what TypeScript namespaces are, how they compile to runtime objects, why ES modules replaced them, and when namespaces still make sense today.
Expected Interview Answer
A namespace is TypeScript's own construct (`namespace Shapes { ... }`) for grouping related code under one named object to avoid global naming collisions, predating ES modules and now considered legacy in favor of standard `import`/`export` module syntax.
Declaring `namespace Shapes { export class Circle {} }` compiles to an IIFE that attaches `Circle` onto a `Shapes` object, so consumers reference `Shapes.Circle` — this genuinely emits runtime JavaScript, unlike most pure type constructs. Namespaces can span multiple files using `/// <reference path=... />` directives, which was useful before bundlers and ES modules were standard, but that pattern doesn't scale well with modern tooling like webpack or ESM. Today, the TypeScript team and most style guides recommend ES modules (`export`/`import`) for code organization and reserve namespaces mainly for global ambient type declarations, like augmenting third-party `.d.ts` files. Namespaces and ES modules can technically coexist, but mixing them in application code is discouraged.
- Groups related code under one name, reducing global scope pollution
- Still useful for declaring ambient/global types in `.d.ts` files
- Supported natively without a bundler, historically simpler for scripts
- Can merge across multiple `namespace` blocks like interfaces do
- Clear migration target: ES modules replace nearly all modern use cases
AI Mentor Explanation
A namespace is like an old scoring convention where every player from one club is announced with the club name prefixed, 'Mumbai Indians: Rohit', to avoid confusing him with a same-named player on another team. Modern scoreboards instead use separate digital team panels altogether, the way ES modules replaced namespaces as the standard way to keep code from different sources from colliding.
Step-by-Step Explanation
Step 1
Declare a namespace
`namespace Shapes { export class Circle {} }` groups related declarations under the `Shapes` name.
Step 2
Access members
Consumers reference `Shapes.Circle`, since only exported members inside the namespace are visible outside it.
Step 3
Compiles to a real object
TypeScript emits an IIFE that builds an actual `Shapes` object at runtime, unlike interfaces and most types which are erased.
Step 4
Span multiple files (legacy)
`/// <reference path="./other.ts" />` let namespaces merge declarations across files before ES modules were standard.
Step 5
Prefer ES modules today
Modern code should use `export`/`import`; namespaces are now mainly reserved for ambient global type declarations in `.d.ts` files.
What Interviewer Expects
- Knows namespaces predate and are largely superseded by ES modules
- Understands a namespace compiles to a real runtime object (an IIFE)
- Can explain when namespaces still make sense (ambient/global `.d.ts` declarations)
- Knows namespaces support declaration merging similar to interfaces
- Avoids recommending namespaces for new application code organization
Common Mistakes
- Using namespaces for new application code instead of ES modules
- Assuming namespaces are erased at compile time like most type constructs
- Mixing `/// <reference>` namespace files with a bundler-based ES module setup
- Confusing a TypeScript namespace with a JavaScript module or package
Best Answer (HR Friendly)
“A namespace is an older TypeScript feature for grouping related code together under one name to avoid naming clashes, similar in spirit to folders for code. Modern TypeScript projects mostly use standard JavaScript import/export instead, and reserve namespaces for special cases like describing global types.”
Code Example
namespace Shapes {
export class Circle {
constructor(public radius: number) {}
}
}
const c = new Shapes.Circle(5); // Shapes is a real runtime object
// Modern preferred equivalent:
// export class Circle { constructor(public radius: number) {} }
// import { Circle } from './shapes';Follow-up Questions
- Why are ES modules generally preferred over namespaces today?
- In what scenario would you still legitimately reach for a namespace?
- How do namespaces support declaration merging?
- What does `/// <reference path=... />` do and why is it considered legacy?
- Can namespaces and ES modules coexist in the same project?
MCQ Practice
1. What does a TypeScript `namespace` compile down to at runtime?
Namespaces emit an actual IIFE that attaches members onto a runtime object, unlike interfaces and most type constructs which are erased.
2. What is the modern recommended replacement for namespaces in application code?
Standard ES module `import`/`export` syntax is now the recommended way to organize TypeScript code instead of namespaces.
3. Where do namespaces still commonly appear in modern TypeScript?
Namespaces remain useful for describing global ambient types, such as augmenting third-party .d.ts declaration files.
Flash Cards
What does a namespace compile to at runtime? — A real JavaScript object created via an IIFE, unlike most erased type constructs.
What has largely replaced namespaces in modern TypeScript? — ES modules (`import`/`export`).
Where do namespaces still make sense today? — Ambient/global type declarations, e.g. augmenting third-party .d.ts files.
Do namespaces support declaration merging? — Yes — multiple `namespace` blocks with the same name merge together, similar to interfaces.