TypeScript by Example

Module Resolution

moduleResolution, path aliases, node16/nodenext imports, and isolatedModules for single-file transpilers.

moduleResolution controls how TypeScript resolves import specifiers. A mismatch between TypeScript and your runtime toolchain causes painful production-only failures.

bundler matches Vite, esbuild, and Next.js. node16 and nodenext follow Node ESM rules, including explicit .js extensions for relative imports.

{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "module": "ESNext",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  }
}
import { Button } from "@/components/Button";
// node16 relative ESM may need: import { helper } from "./helper.js";

isolatedModules: true requires every file to be transformable by tools that compile one file at a time.

// Ambiguous under isolated single-file builds:
// export { SomeType } from "./types";
 
// Clear and stripped from emitted JavaScript:
export type { SomeType } from "./types";
 
type Direction = "UP" | "DOWN";

In production

Keep tsconfig aliases and bundler aliases in sync. Set isolatedModules: true early if your build uses swc, esbuild, Babel, or any single-file TypeScript transform.

Enjoyed this? Get more software craft delivered to your inbox.