</>
Skip to content
TypeScript lessons (23/31)

TypeScript — Modules

Named exports

// math.ts
export function add(a: number, b: number): number {
    return a + b;
}

export function multiply(a: number, b: number): number {
    return a * b;
}

export const PI = 3.14159;

export interface Point {
    x: number;
    y: number;
}
// app.ts
import { add, multiply, PI, Point } from "./math";

console.log(add(3, 4));       // 7
console.log(PI);              // 3.14159

const p: Point = { x: 1, y: 2 };

Default exports

// logger.ts
export default class Logger {
    log(message: string): void {
        console.log(`[LOG] ${message}`);
    }
}
// app.ts
import Logger from "./logger";

const logger = new Logger();
logger.log("Hello");

Re-exporting

// types.ts
export interface User {
    id: string;
    name: string;
}

export interface Post {
    id: string;
    title: string;
    body: string;
}

// index.ts (barrel file)
export { User, Post } from "./types";
export { default as Logger } from "./logger";
export { add, multiply } from "./math";

Namespace imports

import * as Math from "./math";

console.log(Math.add(3, 4));
console.log(Math.PI);

Type-only imports

// Import only the type (removed at compile time)
import type { User } from "./types";

// Or inline
import { type User, type Post } from "./types";

Dynamic imports

async function loadModule() {
    const { add } = await import("./math");
    console.log(add(3, 4));
}

// Conditional import
if (process.env.NODE_ENV === "development") {
    const devTools = await import("./dev-tools");
    devTools.init();
}

Module resolution

TypeScript resolves modules using tsconfig.json:

{
  "compilerOptions": {
    "moduleResolution": "node",
    "baseUrl": "./src",
    "paths": {
      "@utils/*": ["utils/*"],
      "@types/*": ["types/*"]
    }
  }
}
// Now you can import with aliases
import { formatDate } from "@utils/date";
import { User } from "@types/models";

Ambient modules

Declare types for untyped packages:

// types/some-lib.d.ts
declare module "some-lib" {
    export function doSomething(input: string): number;
    export interface Config {
        debug: boolean;
        timeout: number;
    }
}

// Now you can import
import { doSomething, Config } from "some-lib";

Common patterns

// Barrel pattern (index.ts)
export * from "./user";
export * from "./post";
export * from "./comment";

// Re-export with rename
export { UserService as UserServiceV2 } from "./user-service";

// Default export pattern
export { default } from "./main";

// Type export
export type { User, Post, Comment } from "./types";

ESM vs CommonJS

// tsconfig.json
{
  "compilerOptions": {
    "module": "ESNext",      // Modern ESM
    "module": "CommonJS",    // Node.js legacy
    "module": "NodeNext"     // Node.js ESM
  }
}

Mini Practice

Write TypeScript code that:

  1. Creates a module with named and default exports
  2. Imports using named, default, and namespace syntax
  3. Creates a barrel file for re-exporting
  4. Uses dynamic import() for lazy loading

Up Next

In the next lesson, you'll learn about Configuration — setting up tsconfig.json.

Related Topics

Frequently Asked Questions about Modules

What is Modules in TypeScript?

Modules is a fundamental concept in TypeScript. This lesson explains it step by step with clear examples, making it easy for beginners to understand.

How do I learn Modules?

Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Modules.

Why is Modules important in TypeScript?

Modules is essential for TypeScript development. Understanding this concept will help you write better code and solve real-world problems more effectively.