Modules & Namespaces: Code Organization
As your application grows, keeping all your code in one file becomes impossible. TypeScript provides multiple ways to organize and share code across your project, primarily through Modules and Namespaces.
1. ES Modules (The Industry Standard)
TypeScript uses the standard ECMAScript module syntax (import/export). Any file containing a top-level import or export is considered a module.
Named Exports
// math.ts
export const PI = 3.14;
export function add(a: number, b: number) { return a + b; }
// app.ts
import { PI, add } from "./math";
Default Exports
Each file can have exactly one default export.
// Logger.ts
export default class Logger {
log(msg: string) { console.log(msg); }
}
// app.ts
import MyLogger from "./Logger"; // You can name it anything
2. Barrel Exports (Re-exporting)
To simplify imports, you can create an index.ts file in a folder that re-exports everything from that folder. This is known as a Barrel.
// components/index.ts
export * from "./Button";
export * from "./Input";
export { default as Header } from "./Header";
// app.ts
import { Button, Input, Header } from "./components";
3. Namespaces (Internal Modules)
Namespaces were common in older TypeScript versions to group related code and avoid global scope pollution. In modern development, ES Modules are preferred, but Namespaces are still useful for legacy code or specific structural needs.
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean;
}
export const numberRegexp = /^[0-9]+$/;
}
let validator: Validation.StringValidator;
4. Ambient Modules and .d.ts Files
Sometimes you use libraries that are written in plain JavaScript. To use them in TypeScript, you need a Declaration File (.d.ts). These files contain only type information and no implementation code.
Using @types
Most popular libraries have community-maintained types.
npm install --save-dev @types/lodash
Writing Your Own
If a library has no types, you can declare it yourself:
// global.d.ts
declare module "my-old-library" {
export function doSomething(n: number): void;
}
5. Module Resolution Strategies
TypeScript has a sophisticated system for finding files.
- Relative Imports:
./utils,../types. - Non-relative Imports:
react,lodash. TypeScript looks innode_modules.
Pro-Tip: You can configure Path Aliases in tsconfig.json to avoid ugly imports like ../../../utils.
"paths": {
"@utils/*": ["src/utils/*"]
}
6. Summary
- ES Modules are the standard for modern JS/TS.
- Barrels keep your import lists clean.
- Namespaces are for internal organization or legacy support.
- Declaration files bridge the gap between TS and JS libraries.