TS Namespaces
A namespace groups related code under a name. They predate ES modules and are now rarely used for new code — but you'll meet them in legacy projects and in some declaration files.
Declaring
TS
namespace Shop {
export interface Order { id: number; total: number; }
export class OrderService {
all(): Order[] { return []; }
}
}
const svc = new Shop.OrderService();
const orders: Shop.Order[] = svc.all();
Nested namespaces
TS
namespace Shop.Billing {
export class Invoice {
constructor(public amount: number) {}
ref() { return 'INV-001'; }
}
}
const inv = new Shop.Billing.Invoice(100);
Aliasing with import
TS
import Billing = Shop.Billing; const inv2 = new Billing.Invoice(50);
Splitting across files
Namespaces can be declared in multiple files; they merge. Files reference each other with /// <reference path="..." /> at the top — once a common pattern, now mostly avoided.
Use for global type augmentation
The one modern use is augmenting global types — adding things to global namespaces from libraries:
TS
declare global {
namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
API_KEY: string;
}
}
}
// Now process.env.DATABASE_URL is a string, not string | undefined.
vs ES modules
| Namespace | ES module |
|---|---|
| Pre-module era of TS. | Modern standard. |
| Auto-merges across files. | One module per file. |
| Tree-shaking works less well. | Tree-shaking native. |
| Useful for global type augmentation. | Useful for everything else. |
Tip: For new code, use ES modules (
import / export). Reach for namespace only when augmenting globals — and even then sparingly.Example
Example
namespace Shop.Billing {
export class Invoice {
constructor(public amount: number) {}
ref() { return 'INV-001'; }
}
}
const i = new Shop.Billing.Invoice(100);
console.log(i.ref());
Try it Yourself »
Exercise
Mark a member as visible outside the namespace.
namespace Shop {
class Order {} }
Six letters.
Discussion
Loading…