🔷 TypeScript Q66 / 101

Explain isolatedModules option.

AI-Powered Answer ✓ Answered

The `isolatedModules` compiler option in TypeScript is designed to ensure that every `.ts` file can be safely transpiled into JavaScript completely in isolation, without relying on knowledge of other files or the full project graph. This is particularly useful when using transpilers like Babel or `ts-loader`'s `transpileOnly` mode, which process files one by one and don't perform full type-checking or project-wide analysis.

What is `isolatedModules`?

When isolatedModules is enabled, TypeScript enforces certain restrictions to guarantee that a file's JavaScript output will be correct and consistent even if the compiler only processes that single file. This means the transpiler won't peek into other files to resolve types or dependencies, making the transpilation process faster and simpler, mimicking how tools like Babel operate.

Many modern build tools like Babel, ts-loader (with transpileOnly set to true), esbuild, and SWC operate on a file-by-file basis. Without isolatedModules, you might inadvertently write TypeScript code that relies on type information from other files in ways that these isolated transpilers cannot correctly process, leading to runtime errors that a full TypeScript compilation would have caught.

Why is it important?

The primary benefit of isolatedModules is improved build performance and compatibility with transpilation-only workflows. By ensuring each file is self-contained for transpilation purposes, you gain speed and simplicity in your build pipeline. It acts as a safeguard, preventing you from writing code that would lead to incorrect JavaScript output or runtime errors when processed by an isolated transpiler.

How does it enforce single-file transpilation?

isolatedModules restricts language features that require cross-file knowledge for correct transpilation. If you try to use such features, TypeScript will emit a compilation error, even if the code would type-check correctly in a full compilation. This forces you to use syntax that is safe for isolated processing.

  • const enum: const enum members are inlined at compile time. An isolated transpiler wouldn't know the numeric value of an enum member defined in another file, leading to incorrect JS output. You must use regular enums or explicitly export/import individual enum members if needed.
  • **Re-exporting types with export * from**: If you do export * from './types', an isolated transpiler cannot determine which of the exported names are types and which are values. This can lead to issues if value exports are accidentally dropped. Instead, you should use export type * from './types' for type-only re-exports.
  • Importing/Exporting types without type keyword: For type-only imports or exports, you must use import type or export type. For example, import { SomeType } from './foo' should be import type { SomeType } => './foo' if SomeType is only a type.
  • declare class or declare function in a .ts file: These constructs are meant for declaration files (.d.ts). In a .ts file, they can imply that the implementation is provided elsewhere, which an isolated transpiler wouldn't be aware of, potentially leading to missing runtime code.
typescript
/* example.ts */
const enum Status { Active, Inactive }

// This will cause an error with isolatedModules:
// 'const enum' members cannot be accessed in an isolatedModules environment. (2478)
// It needs the value of Status.Active, but an isolated transpiler won't know it.

To fix the const enum issue, you would either use a regular enum or convert it to a plain object or literal type depending on your needs, ensuring the value is directly available without cross-file lookup.

When to use `isolatedModules`?

You should enable isolatedModules in your tsconfig.json whenever your build pipeline involves a transpiler that processes files individually without full type-checking or project context. This commonly includes setups using:

  • Babel (via @babel/preset-typescript)
  • ts-loader with transpileOnly: true (in Webpack)
  • esbuild
  • SWC
  • Any other tool that performs TypeScript-to-JavaScript transformation on a file-by-file basis.

Even if you eventually run tsc for full type-checking, enabling isolatedModules during the development/build step with an isolated transpiler acts as an excellent safety net, catching potential problems early.

Key Takeaways

  • isolatedModules ensures that each TypeScript file can be safely transpiled to JavaScript in isolation.
  • It's crucial when using build tools like Babel, esbuild, or ts-loader with transpileOnly.
  • It restricts certain language features (like const enum, specific type re-exports) that require cross-file knowledge.
  • Enabling it helps prevent subtle runtime errors that can arise from partial compilation by isolated transpilers.
  • It promotes a safer and more performant build process for many modern JavaScript projects.