TypeScript's Older Module Mechanism
Namespaces
Namespaces predate ES modules and still appear in declaration files. Know what they look like even if you'd never write new ones.
What you'll learn
- Read namespace declarations
- Know why ES modules replaced them
- Recognize where namespaces still legitimately appear
A namespace is a TS-specific way to group related types and values under a single name. Before ES modules, this was how you avoided global pollution.
The Syntax
namespace Geometry {
export interface Point { x: number; y: number }
export function distance(a: Point, b: Point): number {
return Math.hypot(a.x - b.x, a.y - b.y);
}
}
const p: Geometry.Point = { x: 0, y: 0 };
const q: Geometry.Point = { x: 3, y: 4 };
Geometry.distance(p, q); // 5 Everything inside namespace Geometry { ... } is reachable via
Geometry.thing. Items must be export-ed to be visible outside.
Why ES Modules Won
ES modules give you the same scoping AND:
- Tree-shakeable (bundlers can drop unused exports)
- Tooling-friendly (every file is its own scope)
- Same syntax across JS and TS
- Compatible with the rest of the ecosystem
For new code, you almost always want import / export rather
than namespace.
Where You’ll Still See Namespaces
Ambient declarations for global APIs — for example, the DOM:
declare namespace ServiceWorker {
interface FetchEvent { /* ... */ }
} Augmenting global types — adding fields to window, for
example:
declare global {
interface Window {
myAnalytics: { track(event: string): void };
}
} (Not a namespace literally, but the same family of declarations.)
Don’t Write New Ones
Files-as-modules is the right tool. Namespaces are mostly there
for backwards compatibility and .d.ts ergonomics.
End of Chapter
That wraps OOP. Next chapter: real-world TS — config, modules, declaration files, and integration with React and Node.
`tsconfig.json` →