TypeScript Modules and Imports
A module is a TypeScript file that keeps its code private by default. Variables, functions, classes, and types inside a module are not visible to other files unless they are explicitly exported. Another file gains access to them by importing them. This system organizes large codebases into focused, manageable files and prevents naming conflicts between different parts of an application.
Why Modules?
Without modules — everything in one file:
+----------------------------------------------+
| app.ts |
| function validateEmail() { ... } |
| function calculateTax() { ... } |
| function renderPage() { ... } |
| class UserManager { ... } |
| class ProductManager { ... } |
+----------------------------------------------+
Hard to navigate, maintain, and reuse.
With modules — each file has one responsibility:
+-----------------+ +------------------+ +------------------+
| utils/ | | services/ | | models/ |
| validation.ts | | tax.ts | | user.ts |
| Exports: | | Exports: | | Exports: |
| validateEmail() | | calculateTax() | | class User |
+-----------------+ +------------------+ +------------------+
| | |
+------------ app.ts imports all ---+-----------+
Exporting from a Module
Named Exports
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
export const PI: number = 3.14159;
export type MathResult = {
value: number;
operation: string;
};
Export After Declaration
// utils.ts
function formatCurrency(amount: number, symbol: string = "₹"): string {
return symbol + amount.toFixed(2);
}
function capitalize(text: string): string {
return text.charAt(0).toUpperCase() + text.slice(1);
}
// Export multiple at the end
export { formatCurrency, capitalize };
Export with Rename
// helpers.ts
function calculateGST(amount: number): number {
return amount * 0.18;
}
export { calculateGST as computeGST };
// Imported as: computeGST — original name stays private
Default Exports
Each module can have one default export. A default export represents the main item the module provides. It is imported without curly braces and can be given any name by the importer.
// logger.ts
export default class Logger {
log(message: string): void {
console.log("[LOG] " + new Date().toISOString() + ": " + message);
}
error(message: string): void {
console.log("[ERROR] " + message);
}
}
Importing a Module
Named Imports
// app.ts
import { add, subtract, PI } from "./math";
console.log(add(10, 5)); // 15
console.log(subtract(10, 5)); // 5
console.log(PI); // 3.14159
Renamed Import
import { formatCurrency as format } from "./utils";
console.log(format(1999)); // ₹1999.00
Namespace Import (Import All)
import * as MathUtils from "./math"; console.log(MathUtils.add(4, 6)); // 10 console.log(MathUtils.PI); // 3.14159
Default Import
import Logger from "./logger"; // Any name works for default import
import MyLogger from "./logger"; // Same module, different name — both valid
let log = new Logger();
log.log("App started"); // [LOG] 2025-03-21T...: App started
Mixed Import (Default + Named)
// config.ts
export default class AppConfig {
appName: string = "eStudy247";
}
export const VERSION: string = "2.0.0";
export const ENVIRONMENT: string = "production";
// app.ts
import AppConfig, { VERSION, ENVIRONMENT } from "./config";
let config = new AppConfig();
console.log(config.appName + " v" + VERSION); // eStudy247 v2.0.0
Re-Exporting
A module can re-export items from another module, creating a single entry point (called a barrel file) for related exports.
Without barrel:
import { add } from "./math/add";
import { format } from "./utils/format";
import Logger from "./logging/logger";
With barrel (index.ts re-exports everything):
import { add, format, Logger } from "./index";
// index.ts — barrel file
export { add, subtract, PI } from "./math";
export { formatCurrency, capitalize } from "./utils";
export { default as Logger } from "./logger";
export type { MathResult } from "./math";
Type-Only Imports and Exports
TypeScript supports importing and exporting types specifically. Type-only imports are removed completely during compilation, resulting in smaller JavaScript output.
// types.ts
export type UserId = number | string;
export type CourseStatus = "draft" | "published" | "archived";
export interface CourseData {
id: UserId;
title: string;
status: CourseStatus;
}
// app.ts
import type { UserId, CourseData } from "./types";
// These imports vanish in the compiled .js file
let id: UserId = 101;
let course: CourseData = { id: 101, title: "TypeScript", status: "published" };
Module File Structure
Typical TypeScript Project Structure: src/ ├── models/ │ ├── user.ts ← export interface User │ ├── course.ts ← export interface Course │ └── index.ts ← barrel: re-exports User, Course │ ├── services/ │ ├── userService.ts ← export function getUser() │ ├── courseService.ts ← export function getCourses() │ └── index.ts ← barrel: re-exports all services │ ├── utils/ │ ├── format.ts ← export function formatDate() │ └── validate.ts ← export function validateEmail() │ └── app.ts ← main entry point
Module Resolution
| Import Path | Meaning | Example |
|---|---|---|
| Relative path | Relative to current file | ./math, ../utils |
| Absolute path | From project root (with path mapping) | @/utils/format |
| npm package | From node_modules | lodash, axios |
Practical Example
// models/student.ts
export interface Student {
studentId: number;
name: string;
email: string;
grade: string;
}
export type StudentSummary = Pick<Student, "studentId" | "name" | "grade">;
// services/studentService.ts
import { Student, StudentSummary } from "../models/student";
const students: Student[] = [
{ studentId: 1, name: "Aarti", email: "aarti@mail.com", grade: "A" },
{ studentId: 2, name: "Bharat", email: "bharat@mail.com", grade: "B" },
{ studentId: 3, name: "Chitra", email: "chitra@mail.com", grade: "A+" }
];
export function getAllStudents(): Student[] {
return students;
}
export function getSummaries(): StudentSummary[] {
return students.map(({ studentId, name, grade }) => ({ studentId, name, grade }));
}
// app.ts
import { getAllStudents, getSummaries } from "./services/studentService";
let all = getAllStudents();
console.log("Total Students: " + all.length); // Total Students: 3
let summaries = getSummaries();
summaries.forEach(s => {
console.log(s.studentId + ". " + s.name + " | " + s.grade);
});
// 1. Aarti | A
// 2. Bharat | B
// 3. Chitra | A+
