Tutorials Logic, IN info@tutorialslogic.com

TypeScript Modules: import, export and Type-Only Imports

What Modules Solve

A TypeScript module is a file that exports or imports something. Modules keep code organized by giving each file a clear responsibility and by making dependencies explicit.

Without modules, large projects quickly become difficult to navigate. With modules, utilities, models, services, components, and API clients can live in separate files while still working together through imports and exports.

TypeScript modules use JavaScript module syntax. TypeScript adds type checking, type-only imports, and compiler settings that control how modules are resolved and emitted.

Named Exports - TypeScript Example

Named Exports - TypeScript Example
export function add(a: number, b: number): number {
  return a + b;
}

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

export const TAX_RATE = 0.18;

Named Exports

Named exports are explicit and easy to search. A file can export many named values, and importers choose exactly what they need.

Named exports are usually a strong default for utilities, constants, shared models, service functions, and feature helpers because refactors are clearer and accidental name changes are easier to catch.

Import Named Values

Import Named Values
import { add, TAX_RATE } from "./math";

export function calculateInvoice(subtotal: number): number {
  const tax = subtotal * TAX_RATE;
  return add(subtotal, tax);
}

Default Exports

A default export represents the main value from a file. Default exports are common for page components, one primary class, or a module that naturally exposes one main thing.

Use default exports intentionally. In larger shared utility files, named exports are often easier to maintain because every imported name is tied to the exported name.

Export Style Common Use
Named export Utilities, constants, models, multiple public values.
Default export One main component, class, or service from a file.
Mixed exports Use carefully so the file API stays obvious.

Default Export

Default Export
export default class UserService {
  findName(id: number): string {
    return id === 1 ? "Admin" : "Guest";
  }
}

// app.ts
import UserService from "./UserService";

const service = new UserService();
console.log(service.findName(1));

Importing Types Separately

import type imports only type information. The import is erased from compiled JavaScript because interfaces and type aliases do not exist at runtime.

Using import type makes intent clear and can avoid build problems in projects that enforce isolated modules or strict module syntax. It also helps developers see which dependencies are runtime dependencies and which are only for checking.

Type-Only Import

Type-Only Import
import { calculateInvoice } from "./billing";
import type { User } from "./types";

const user: User = {
  id: 1,
  name: "Admin",
};

console.log(user.name, calculateInvoice(1000));

Re-exporting from an Index File

A feature folder may contain several files. An index.ts file can re-export the public pieces so other parts of the app import from one stable path.

Use this carefully. Re-exporting everything from everywhere can create confusing dependency graphs. Export only the API that other folders should depend on.

Barrel Export

Barrel Export
export type { User, UserRole } from "./user.types";
export { createUserService } from "./user.service";
export { validateUserInput } from "./user.validation";

Path Aliases

Path aliases make imports shorter and more stable. Instead of importing from ../../../services/users, a project might use @/services/users.

Aliases are usually configured in tsconfig.json and must also be understood by the bundler or runtime. TypeScript can type-check an alias, but the tool that runs the code must know how to resolve it too.

Alias Import

Alias Import
import { createUserService } from "@/features/users";
import type { User } from "@/features/users";

export async function loadProfile(id: number): Promise<User | null> {
  const service = createUserService();
  return service.findById(id);
}

Module Boundaries

Good modules have clear ownership. A feature module should expose what other parts of the app need and keep internal helpers private. This prevents unrelated code from depending on implementation details.

If a shared folder becomes a dumping ground, it becomes hard to understand. Prefer specific shared modules such as date, money, http, or validation over vague folders like misc.

Module Choice Effect
Small focused file Easy to test and reuse.
Feature index file Clean public imports for a folder.
Deep private import Can create fragile dependencies.
Circular import Can cause confusing runtime behavior.

Common Module Mistakes

Most module problems come from unclear ownership. A shared folder should not become a dumping ground, and feature modules should avoid reaching deeply into each other’s private files.

Keep imports pointed at public entry points when possible. If a file is imported from many unrelated places, it may belong in a shared utility package or it may need a clearer abstraction.

  • Do not mix default and named exports in the same file unless there is a clear reason.
  • Avoid long relative paths such as ../../../utils by organizing modules or using configured path aliases.
  • Use import type for interfaces and aliases that are only needed for checking.
  • Keep feature internals private by exporting only the pieces other modules should use.
  • Avoid circular imports by moving shared contracts into smaller neutral modules.
Before you move on

TypeScript Modules: import, export and Type-Only Imports Mastery Check

6 checks
  • TypeScript modules build on JavaScript import/export syntax.
  • Value imports become runtime JavaScript.
  • import type is erased from JavaScript output.
  • Index files can expose a clean public API for a folder.
  • Path aliases need support from TypeScript and the runtime or bundler.
  • Good module boundaries make large TypeScript projects easier to maintain.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.