Modules isolate scope. Use ESM `import/export`. Add `import type` / `export type` to avoid pulling runtime code for types. Namespaces are legacy; prefer modules. Be mindful of path aliases and interop (CJS vs ESM). **Why it matters:** • Mixing default/named imports across CJS/ESM can silently break at runtime • import type keeps bundles small and avoids unexpected side effects • Consistent path aliases keep tooling (Vite/TS/Jest) aligned
import type { User } from "./types";
export function getUser(id: string): Promise<User> { ... }// types.ts
export type User = { id: string; name: string };
// api.ts
import type { User } from "./types";
export async function fetchUser(id: string): Promise<User> {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
// index.ts
export * from "./api";
export type { User } from "./types";
// Legacy namespace (avoid unless needed)
// namespace Legacy { export const version = "1.0"; }Understanding Modules & Namespaces is fundamental to mastering TypeScript. Practice with the examples above and experiment with variations to solidify your knowledge.