JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeQuestionstypescript
PrevNext

Learn the concept

Module System

typescript
mid
modules

How do TypeScript modules work and what's the difference between import types?

modules
import
export
declaration-files
types
Quick Answer

TypeScript supports ES6 modules with import/export syntax. Use 'import type' for type-only imports (erased at compile time). Declaration files (.d.ts) provide types for JavaScript libraries. Module resolution follows Node.js or bundler strategies.

Detailed Explanation

Module Syntax:

  • ES6 modules: import/export
  • Named exports: export { name }
  • Default exports: export default
  • Namespace imports: import * as

Type-Only Imports:

  • import type { Type }: Types only, erased at runtime
  • import { type Type }: Inline type modifier
  • Prevents including unused runtime code

Declaration Files (.d.ts):

  • Type definitions without implementation
  • For typing JavaScript libraries
  • @types/* packages from DefinitelyTyped

Module Resolution:

  • Node16/NodeNext: Recommended for Node.js ESM projects
  • Bundler: For webpack/vite/esbuild
  • Node10: Legacy Node.js resolution (renamed from Node)
  • Classic: Deprecated, avoid in new projects

Modern Settings:

  • verbatimModuleSyntax (TS 5.0+): Enforces explicit import type, replacing deprecated isolatedModules/importsNotUsedAsValues
  • import defer * as mod from 'module' (TS 5.9): Deferred module evaluation
  • .mts/.cts extensions for explicit ESM/CJS module files

Code Examples

Import and export syntaxTypeScript
// === Exporting ===
// Named exports
export const PI = 3.14159;
export function add(a: number, b: number): number {
  return a + b;
}
export interface User {
  id: number;
  name: string;
}

// Default export
export default class Calculator {
  add(a: number, b: number) { return a + b; }
}

// Re-exports
export { User as UserType } from './types';
export * from './utils';
export * as MathUtils from './math';

// === Importing ===
// Named imports
import { PI, add, User } from './math';

// Default import
import Calculator from './calculator';

// Namespace import
import * as Math from './math';
Math.add(1, 2);

// Combined
import Calculator, { add, PI } from './calculator';

Real-World Applications

Use Cases

Monorepo Package Publishing

Configuring dual CJS/ESM exports with proper type declarations using package.json exports field

Library Type Augmentation

Extending third-party library types (Express Request, Next.js PageProps) via module augmentation

Barrel File Organization

Organizing large codebases with index.ts barrel files using type-only re-exports

Mini Projects

Dual-Format NPM Package

intermediate

Create a library that publishes both ESM and CJS with correct .d.ts, .d.mts, and .d.cts declarations

Module Augmentation Demo

intermediate

Build a plugin system that extends a core library's types via declaration merging

Industry Examples

tsdown

TypeScript-first bundler that handles dual CJS/ESM output with declaration file generation

DefinitelyTyped

Community-maintained type declarations for JavaScript packages

Resources

TypeScript - Modules

docs

TypeScript - Declaration Files

docs

Related Questions

What are generics in TypeScript and how do you use them?

mid
generics
Previous
What are TypeScript's built-in utility types and when do you use them?
Next
What are enums in TypeScript and when should you use them vs union types?
PrevNext