Modules in TypeScript: A Comprehensive Guide
A module is a file that exports things other files can import. That's it. No magic.
23 Apr 2024

A module is a file that exports things other files can import. That's it. No magic.
In TypeScript, any file with a top-level import or export is treated as a module. Files without them are treated as global scripts.
The old way: namespaces
TypeScript originally used the module keyword (later renamed to namespace) to group code:
namespace MyModule {
export function sayHello(name: string) {
console.log(`Hello, ${name}!`);
}
}
This still works, but it's a legacy pattern. Modern TypeScript uses ES modules.
The modern way: ES modules
Export from one file, import in another:
// greet.ts
export function sayHello(name: string) {
console.log(`Hello, ${name}!`);
}
// app.ts
import { sayHello } from './greet';
sayHello('John');
Each file is its own scope. Nothing leaks out unless you explicitly export it.
The trade-off
Modules give you encapsulation, clear dependency graphs, and tree-shaking. You can see exactly what each file depends on.
The cost: module resolution can be confusing. TypeScript has moduleResolution: "node", "node16", "bundler" — each with different rules about file extensions, package.json exports, and .js vs .ts imports. Getting the tsconfig.json right is half the battle.
My advice: use ES modules. Set "module": "esnext" and "moduleResolution": "bundler" if you're using a bundler. Forget namespaces unless you're maintaining legacy code.