Modules & Namespaces
TypeScript modules and namespaces help you organize and structure your code. Let's learn how to use them effectively!
ES Modules
ES Modules are the standard way to organize code in modern TypeScript/JavaScript. They allow you to split your code into separate files and share code between them.
// math.ts
export const add = (a: number, b: number): number => a + b;
export const subtract = (a: number, b: number): number => a - b;
// You can also have a default export
export default class Calculator {
add(a: number, b: number): number {
return a + b;
}
}
// main.ts
import Calculator, { add, subtract } from './math';
const result = add(5, 3); // 8
const diff = subtract(10, 4); // 6
const calc = new Calculator();
const sum = calc.add(2, 3); // 5
Namespaces
While modules are the preferred way to organize code, TypeScript also supports namespaces (formerly known as "internal modules"). They're useful for bundling related functionality.
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean;
}
export class LettersOnlyValidator implements StringValidator {
isValid(s: string): boolean {
return /^[A-Za-z]+$/.test(s);
}
}
}
// Using the namespace
let validator = new Validation.LettersOnlyValidator();
let result = validator.isValid("Hello"); // true
Import/Export Types
TypeScript allows you to import and export types, interfaces, and other type-only declarations:
// types.ts
export interface User {
id: number;
name: string;
}
export type UserRole = 'admin' | 'user' | 'guest';
// Using type-only imports
import type { User, UserRole } from './types';
Module Resolution
TypeScript supports different module resolution strategies:
- Classic: Legacy resolution strategy
- Node: Follows Node.js module resolution rules
- Modern: Uses ECMAScript module resolution rules
You can configure this in your tsconfig.json:
{
"compilerOptions": {
"moduleResolution": "node",
// or "classic", or "bundler"
}
}
Best Practices
-
Prefer ES Modules over Namespaces
- ES Modules are the standard
- Better tooling support
- Tree-shaking friendly
-
Use Barrel Files
// index.ts (barrel file)
export * from './user';
export * from './product';
export * from './order'; -
Explicit Imports
// Good
import { useState, useEffect } from 'react';
// Avoid
import * as React from 'react'; -
Type-Only Imports
- Use
import typewhen importing only types - Helps with tree-shaking and build optimization
- Use
Remember that good module organization is key to maintaining a scalable TypeScript project. Choose your exports carefully and keep your modules focused and cohesive.