Chapter 31: TypeScript Namespaces
TypeScript Namespaces very calmly, slowly, and honestly, like we’re sitting together with a laptop, chai on the table, and we’re typing small examples one by one until you really understand when & why people still use them in 2026 (and when they almost never should).
1. First — the most important honest sentence you should remember
Namespaces in modern TypeScript (2025–2026) are considered a legacy feature in almost every new project.
They were very popular in the early days of TypeScript (2012–2018), but today most experienced teams avoid them for application code.
You will still see them in two main places in 2026:
- Very old / long-lived enterprise codebases
- Some declaration files (.d.ts) — especially ambient / global declarations
So we will learn them properly — but also learn why most people recommend alternatives now.
2. What problem were namespaces originally solving?
Before ES modules (import / export) became standard in browsers & Node.js, JavaScript had no built-in way to organize code into modules.
People used:
- IIFE (Immediately Invoked Function Expressions)
- Revealing module pattern
- Global objects with sub-objects
Namespaces were TypeScript’s answer to give named hierarchical scopes + prevent polluting the global namespace.
|
0 1 2 3 4 5 6 7 8 9 |
// Without namespaces (old style) var MyApp = MyApp || {}; MyApp.Utils = MyApp.Utils || {}; MyApp.Utils.formatDate = function(d) { ... }; |
With namespaces → cleaner syntax + type safety.
3. Basic syntax — the classic way people used to write it
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
namespace MyApp { export interface User { id: number; name: string; } export class UserService { getUser(id: number): User { return { id, name: "Demo" }; } } export const version = "1.2.3"; // nested namespace export namespace Utils { export function formatDate(date: Date): string { return date.toISOString(); } } } // Usage (global access — no import needed) const service = new MyApp.UserService(); const formatted = MyApp.Utils.formatDate(new Date()); console.log(MyApp.version); |
Notice:
- export makes things visible outside the namespace
- You access with dot notation — MyApp.XXX
- No import statement needed (ambient / global)
4. Nested namespaces & splitting across files
You can split one namespace across multiple files (very common in old large projects).
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// file: core.ts namespace Company { export const name = "Webliance"; } // file: models.ts namespace Company { export interface Employee { id: number; name: string; } } // file: services.ts namespace Company { export class EmployeeService { getAll(): Company.Employee[] { return [{ id: 1, name: "Rahul" }]; } } } |
TypeScript merges all declarations with the same namespace name (declaration merging).
5. Important modifiers inside namespaces
| Keyword | Meaning inside namespace | Example use-case |
|---|---|---|
| export | Makes the member visible outside the namespace | Almost everything you want to use |
| (no keyword) | Internal to the namespace — not exported | Private helpers, internal types |
| export namespace | Creates a sub-namespace | Grouping related utilities |
| export = | (legacy) Default export of the whole namespace | Rare — CommonJS style |
6. Modern reality — why almost nobody starts new projects with namespaces in 2026
| Reason | Explanation | Recommended alternative (2026) |
|---|---|---|
| ES modules are now universal | import / export works in browser, Node, Deno, Bun | Regular ES modules + import / export |
| Tree-shaking & bundlers love ESM | Namespaces are harder to tree-shake | ESM + barrel files if needed |
| Tooling is better with files-as-modules | VS Code, ESLint, Vite, Turbopack, tsc understand files better than namespaces | One file = one module |
| No runtime cost with ESM | Namespaces compile to objects → small runtime overhead | ESM has zero runtime overhead for imports |
| Declaration merging is confusing | Hard to find where something is defined | Colocation + clear file boundaries |
| Global pollution risk | Easy to accidentally leak globals | Explicit imports only |
Official TypeScript handbook (2025–2026) recommendation:
“Avoid namespaces in new code. Use ES modules instead.”
7. When you still see namespaces in 2026 (real cases)
- Ambient / global type declarations (.d.ts files)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
// globals.d.ts declare namespace NodeJS { interface ProcessEnv { API_KEY: string; DATABASE_URL: string; // ... } } |
- Very old libraries that haven’t migrated (some jQuery plugins, old AngularJS code, legacy internal frameworks)
- Internal company monorepos that were started in 2015–2018 and never fully migrated (very common in big enterprises)
- Some DefinitelyTyped @types/* packages still use namespaces for historical reasons
8. Modern replacement patterns (what you should use instead)
Pattern 1: Simple module file
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// user.ts export interface User { id: number; name: string; } export class UserService { getUser(id: number): User { return { id, name: "Sara" }; } } |
|
0 1 2 3 4 5 6 7 8 9 |
// main.ts import { UserService } from './user'; const service = new UserService(); |
Pattern 2: Barrel file (if you want grouped exports)
|
0 1 2 3 4 5 6 7 8 9 |
// index.ts (barrel) export * from './user'; export * from './product'; export * from './order'; |
|
0 1 2 3 4 5 6 |
import { User, UserService } from '@/features/user'; |
Pattern 3: Scoped packages / internal packages in monorepo
|
0 1 2 3 4 5 6 7 8 9 10 11 |
packages/ ├── core/ │ └── index.ts ├── features/ │ └── auth/ │ └── index.ts |
Summary — 2026 honest verdict
| Scenario | Should you use namespaces? | Recommendation |
|---|---|---|
| New greenfield project | No | Use ES modules + files |
| Existing project that already uses them | Maybe keep (migration cost) | Plan gradual migration to ESM |
| Writing .d.ts global declarations | Yes (sometimes) | Use declare namespace only when necessary |
| Learning TypeScript | Yes — understand them | But don’t start new code with them |
Want to practice or compare?
- Show old namespace style vs modern ESM side-by-side
- Convert a small namespace-based example to ESM
- Explain how namespaces compile to JavaScript (what code is emitted)
- Talk about ambient declarations vs module augmentation
Just tell me which direction feels most useful right now 😄
