This episode covers organizing TypeScript code: modern ES modules with import and export, type-only imports and exports, namespaces for ambient declarations, and the right module configuration. You'll understand the recommended organization patterns.

Code crammed into a single file quickly becomes unmaintainable. Episode 10 covers how to split a program into modules — units of code that import each other — and how to export types alongside values. This organization decides whether a project can grow or dies from tangled dependencies.
TypeScript supports two organizational systems: modern ES modules, which are the standard, and namespaces, now more often used for global ambient declarations. Understanding both, plus when to use each, is part of maturity as a TypeScript developer.
Episode 10 examines import and export syntax, type-only imports and exports to stay safe with modern compilers, and module configuration in tsconfig.
Every file with an import or export statement is a module:
export interface Pengguna {
nama: string;
}
export const versi = "1.0.0";
export function sapa(nama: string): string {
return `Halo, ${nama}`;
}The file above exports an interface, a constant, and a function. Other modules import them with the import keyword. With modules, every file has its own scope; only exported symbols can be used outside the file.
import { Pengguna, sapa } from "./pengguna";
const pengguna: Pengguna = { nama: "Budi" };
console.log(sapa(pengguna.nama));The from "./pengguna" clause refers to the file path without an extension. The compiler and bundler resolve that path during build. Named imports make dependencies explicit and easy to trace.
A module can also export a single main value with export default:
export default class ApiClient {
constructor(private baseUrl: string) {}
}A default import doesn't use curly braces. Each module may have only one default export. This pattern is common for components, main classes, or a single function at the heart of a file.
TypeScript separates values and types. This enables imports that only bring in types:
import type { Pengguna } from "./pengguna";
const data: Pengguna = { nama: "Sari" };The declaration import type states that only types are brought in, not runtime values. At compile time, this import is removed entirely. That matters for compilers with isolatedModules and for keeping bundle size down.
Inline syntax is also supported for clarity:
import { sapa, type Pengguna } from "./pengguna";On the same line, sapa is imported as a value and Pengguna as a type. This pattern is concise and clear, widely used in modern codebases.
A namespace groups symbols in one global scope:
namespace Utilitas {
export function formatAngka(n: number): string {
return n.toLocaleString("id-ID");
}
export const satuan = "IDR";
}A namespace places functions and constants under a single name Utilitas. This was once the main way to organize code. Today, ES modules are preferred for application code because they work better with bundlers and force explicit imports.
Namespaces remain useful for environment declaration files, especially when typing global variables:
declare namespace GlobalNya {
interface Config {
apiKey: string;
}
}A declare namespace block describes the shape of a global object without producing runtime code. This pattern is used by many classic libraries and ambient declarations. For applications you write yourself, ES modules remain the primary choice.
Module compilation behavior is controlled from tsconfig:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext"
}
}The module option determines the JavaScript output format, for example NodeNext for Node.js and ESNext for modern bundlers. The moduleResolution option determines how the compiler finds import files. Both must match the runtime environment you use.
Tip
If you're unsure what to pick, let the tooling decide: scaffolding like bun create next-app or npx tsc --init already sets module and moduleResolution that are right for your project.
Episode 10 keeps your code organized: ES modules for application code, type-only imports and exports for modern compiler safety, and namespaces for ambient declarations. You also understand module settings in tsconfig.
Key takeaways:
export default provides one main value per module.import type removes type imports at compile time.module and moduleResolution must match the runtime.In the next episode 11 we'll discuss type guards, narrowing, and type flow control — how to safely narrow a union type down to a concrete type inside branches.