isolatedModules

Flags code that a single-file transpiler such as Babel or esbuild cannot compile correctly.

Signature
"isolatedModules": boolean
  • Added in TypeScript 1.5

Parameters

ParameterTypeDescription
$trueoptionalbooleanBans re-exporting a type without a type modifier, ambient const enum references, namespaces in non-module (global script) files, and other constructs a file-at-a-time transpiler cannot resolve.
$falseoptionalbooleanDefault, unless verbatimModuleSyntax is enabled, which implies this flag.

Return value

Reports errors on constructs whose correct compilation needs whole-program type information. Does not change emit or runtime behaviour.

Errors

Error TS1205 when re-exporting a type without the type modifier; TS1209 when referencing an ambient const enum member; and an error on a namespace in a global script file, which suggests setting moduleDetection to force or adding an empty `export {}`.

Changelog

  • PHP 5.0verbatimModuleSyntax implies isolatedModules, since verbatim emit is precisely what a single-file transpiler can reproduce.
  • PHP 5.5isolatedDeclarations extends the same idea to .d.ts generation, requiring explicit return types so declarations can be emitted file by file.

isolatedModules does not change a single byte of output. It is a compatibility check: it warns you when you write something that tsc can compile — because it sees the whole program — but a file-at-a-time transpiler cannot.

Why the distinction exists

Babel, esbuild, swc and ts.transpileModule process one file with no type information at all. Given export { someType }, such a tool has no way to know that someType is a type with no runtime value, so it emits a real export of a binding that does not exist. The result is a module-not-found or undefined-export error at runtime, from code that compiled cleanly.

What it bans

  • Re-exporting a type without type — write export type { Cents } or export { type Cents }.
  • Ambient const enum members — tsc inlines Numbers.Zero as 0; a lone file cannot, and leaves a dangling reference.
  • Namespaces in a global script file — allowed only in files that already have an import or export. (.d.ts files are exempt.)

When to turn it on

Any project whose real build is done by Vite, Next.js, esbuild or Babel while tsc only type checks. Turning it on late is uncomfortable but mechanical; leaving it off means the two toolchains can disagree in production.

Example

Example · typescript
// tsconfig.json
//   { "compilerOptions": { "isolatedModules": true } }

import { formatCents, type Cents } from "./money.js";

// export { Cents };        // error TS1205: re-exporting a type needs 'export type'
export type { Cents };      // ✔ explicitly type-only, erased
export { formatCents };     // ✔ a real runtime value

// declare const enum Size { S = 1 }  // referencing Size.S is error TS1209
enum Size { S = 1 }                   // a plain enum is fine: it emits an object

console.log(Size.S, formatCents(500));
// -> 1 $5.00

When to use it

  • Preparing a codebase for a switch from tsc to esbuild, swc or Vite.
  • Preventing const enum usage that silently breaks under a Babel pipeline.
  • Catching type re-exports that a bundler would emit as broken runtime exports.
  • Satisfying the prerequisite implied by verbatimModuleSyntax.

Frequently asked questions

What does isolatedModules actually change?

Nothing about the emitted JavaScript — it only adds errors for constructs a single-file transpiler such as Babel or esbuild cannot compile correctly. Enabling it is therefore risk-free for an existing build and only surfaces latent incompatibilities.

How do I fix "Re-exporting a type when isolatedModules is enabled requires using export type"?

Change export { Foo } to export type { Foo }, or mark the individual name with export { type Foo, bar }. The modifier tells any transpiler that the name has no runtime value without needing type information.

Can I use const enum with isolatedModules?

You can declare a local const enum, but referencing an ambient (declared) const enum member is error TS1209 because only tsc can inline those values. Use a regular enum, or an as const object, when a bundler does your transpilation.

More examples

Why a type re-export is unsafe file-by-file

tsc knows SomeType is a type and elides it; esbuild, seeing one file with no type information, cannot. The type modifier moves that knowledge into the syntax so any transpiler gets it right, which is the entire point of the flag.

Example · typescript
// someModule.ts
export type SomeType = { id: number };
export function someFunction() { return 42; }

// index.ts — as written, without isolatedModules:
//   import { someType, someFunction } from "./someModule.js";
//   export { someType, someFunction };
//
// A single-file transpiler emits BOTH names, including someType,
// which has no runtime value -> SyntaxError or undefined export.

import { type SomeType, someFunction } from "./someModule.js";
export type { SomeType };
export { someFunction };

console.log(someFunction());
// -> 42

const enum and the namespace rule

Both errors point at the same limitation: the transpiler sees one file and cannot know what the rest of the program declares. Note that .d.ts files are exempt from the namespace rule, so ambient declaration files still work normally.

Example · typescript
// 1. Ambient const enums are inlined by tsc, and only by tsc.
//    declare const enum Numbers { Zero = 0, One = 1 }
//    console.log(Numbers.Zero + Numbers.One);
//    tsc emits: console.log(0 + 1);
//    esbuild emits: console.log(Numbers.Zero + Numbers.One);  -> ReferenceError
//    Under isolatedModules this is error TS1209.

// 2. A namespace needs the file to be a module.
export {}; // this line is what makes the namespace below legal

namespace Instantiated {
  export const x = 1;
}

console.log(Instantiated.x);
// -> 1

// Without `export {}`: "Namespaces are not allowed in global script files
// when 'isolatedModules' is enabled." Set moduleDetection to "force"
// to treat every file as a module instead.

Discussion

  • Be the first to comment on this lesson.