TypeScript 76 🔷 Isolated Modules and verbatimModuleSyntax
A TypeScript file is not always compiled by the TypeScript compiler. It may be transpiled by Babel, esbuild, SWC, Vite, or any of the modern bundlers, each of which processes one file at a time and has no knowledge of the other files in the project. When a transpiler sees import { User } from './user', it cannot know whether User is a type or a value, because determining that requires the whole program’s type information — the same information the transpiler does not have. TypeScript solves this with two options that force the developer to write code that is unambiguous per-file: isolatedModules and verbatimModuleSyntax. This chapter covers what the per-file transpilation means, how the two options enforce the rules, the errors they produce, the difference between them, the type-only imports and exports, and the patterns that make a codebase compatible with the modern toolchain.
Key point: isolatedModules tells TypeScript that each file must be transpilable in isolation, without the other files’ type information. It catches the files that cannot be, and it errors on the type-only’s re-exports that are not marked with type, the const enum‘s, the namespace’s, and the ambient’s imports. verbatimModuleSyntax tells TypeScript to emit the imports and exports exactly as written, without eliding the type-only’s or rewriting the ESM to the CommonJS. The two work together: isolatedModules requires the explicit type markers, and verbatimModuleSyntax makes the emitted code match the source. The import type { User } from './user' is the type-only’s import, and the export type { User } is the type-only’s export. The import { type User, greet } is the inline’s mixed. The two options are enabled by the modern configurations, and they are the requirements for the Vite, the esbuild, the SWC, and the Babel.
Why the per-file transpilation matters
The TypeScript compiler has the whole program’s type information. It can determine whether User is a type or a value, and it can elide the type-only’s import. The transpilers do not.
The transpiler’s limitation. The Babel, the esbuild, the SWC, the Vite transpile one file at a time. They do not have the type checker’s information, and they do not know the other files’ exports. The import { User } is the ambiguous’s, and the ambiguity’s is the error’s.
The TypeScript’s workaround. The TypeScript uses the isolatedModules and the verbatimModuleSyntax to force the developer to write the unambiguous code. The import type and the export type are the explicit’s, and the explicit’s is the safe’s.
Why the modern toolchain matters. The Vite, the esbuild, the SWC, the Babel are the fast’s, and the fast’s is the file-by-file’s. The TypeScript’s tsc is the slow’s, and the slow’s is the whole’s. The modern’s toolchain uses the transpilers for the speed, and the speed’s is the design’s.
Why the isolatedModules matters. The isolatedModules is the enforcement’s, and the enforcement’s is the per-file’s. The isolatedModules catches the files’s, and the files’s is the error’s.
Why the verbatimModuleSyntax matters. The verbatimModuleSyntax is the emit’s, and the emit’s is the verbatim’s. The verbatimModuleSyntax makes the emitted code match the source, and the source’s is the predictable’s.
Why the two work together. The two work together, and the together’s is the modern’s. The isolatedModules requires the explicit’s, and the verbatimModuleSyntax makes the emit’s match. The two are the pair, and the pair is the design’s.
Why the errors matter. The errors are the specific’s, and the specific’s is the fix’s. The TS1205‘s, the TS2748‘s, the TS1209‘s are the errors’s. The two are the pair, and the pair is the diagnosis’s.
Why the migration matters. The migration is the incremental’s, and the incremental’s is the safe’s. The import type‘s is the fix’s, and the fix’s is the automated’s. The two are the pair, and the pair is the design’s.
Why the two options are the modern’s. The two options are the modern’s, and the modern’s is the standard’s. The
isolatedModulesand theverbatimModuleSyntaxare the standard’s, and the standard’s is the recommendation’s. The two are the pair, and the pair is the design’s.
The isolatedModules
The isolatedModules: true tells the TypeScript that each file must be transpilable in isolation.
{
"compilerOptions": {
"isolatedModules": true
}
}
The isolatedModules: true is the flag’s, and the flag’s is the per-file’s. The two are the pair, and the pair is the design’s.
Why the isolatedModules matters. The isolatedModules is the enforcement’s, and the enforcement’s is the per-file’s. The isolatedModules catches the files’s, and the files’s is the error’s. The two are the pair, and the pair is the design’s.
The isolatedModules‘s errors. The isolatedModules‘s errors are the TS1205‘s, the TS2748‘s, the TS1209‘s, the TS1284‘s.
// The TS1205's:
export { User } from './user'; // ❌ the type-only's re-export's
export type { User } from './user'; // ✅
// The TS2748's:
const enum Color { Red } // ❌ the const enum's
enum Color { Red } // ✅
// The TS1209's:
declare global { ... } // ❌ the ambient's in the module's
export {}; // ✅ the fix's
The TS1205, the TS2748, the TS1209 are the three, and the three are the errors’s. The two are the pair, and the pair is the design’s.
Why the isolatedModules‘s errors matter. The isolatedModules‘s errors are the specific’s, and the specific’s is the fix’s. The TS1205‘s is the re-export’s, the TS2748‘s is the const enum’s, the TS1209‘s is the ambient’s. The two are the pair, and the pair is the diagnosis’s.
The isolatedModules‘s the per-file’s. The isolatedModules‘s the per-file’s is the transpiler’s, and the transpiler’s is the one-file’s.
// The transpiler sees:
import { User } from './user';
// The transpiler does not know:
// - Is User a type or a value?
// - Should the import be emitted?
The import { User } from './user' is the per-file’s, and the per-file’s is the transpiler’s. The two are the pair, and the pair is the design’s.
Why the isolatedModules‘s the per-file’s matters. The isolatedModules‘s the per-file’s is the transpiler’s, and the transpiler’s is the one-file’s. The isolatedModules‘s is the requirement’s, and the requirement’s is the design’s. The two are the pair, and the pair is the design’s.
The isolatedModules‘s the preserveConstEnums‘s. The isolatedModules‘s the preserveConstEnums‘s is the runtime’s, and the runtime’s is the const’s.
// The isolatedModules with the preserveConstEnums:
const enum Color { Red } // ✅ the runtime's is the emitted's
The const enum Color { Red } is the preserveConstEnums‘s, and the preserveConstEnums‘s is the runtime’s. The two are the pair, and the pair is the design’s.
Why the preserveConstEnums‘s matters. The preserveConstEnums‘s is the runtime’s, and the runtime’s is the const’s. The isolatedModules‘s is the error’s, and the error’s is the cross-file’s. The two are the pair, and the pair is the design’s.
The isolatedModules‘s the verbatimModuleSyntax‘s. The isolatedModules‘s the verbatimModuleSyntax‘s is the pair’s, and the pair’s is the modern’s.
{
"compilerOptions": {
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}
The isolatedModules and the verbatimModuleSyntax are the pair’s, and the pair’s is the modern’s. The two are the pair, and the pair is the design’s.
Why the pair’s matters. The pair’s is the modern’s, and the modern’s is the standard’s. The isolatedModules‘s is the requirement’s, and the verbatimModuleSyntax‘s is the emit’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax
The verbatimModuleSyntax: true tells the TypeScript to emit the imports and exports exactly as written.
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
The verbatimModuleSyntax: true is the flag’s, and the flag’s is the verbatim’s. The two are the pair, and the pair is the design’s.
Why the verbatimModuleSyntax matters. The verbatimModuleSyntax is the emit’s, and the emit’s is the verbatim’s. The verbatimModuleSyntax makes the emitted code match the source, and the source’s is the predictable’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax‘s the requirements. The verbatimModuleSyntax‘s the requirements are the import type‘s and the export type‘s.
// The verbatimModuleSyntax's:
import { User } from './user'; // ❌ the type-only's
import type { User } from './user'; // ✅
export { User }; // ❌ the type-only's
export type { User }; // ✅
The import type { User } and the export type { User } are the requirements’s, and the requirements’s is the explicit’s. The two are the pair, and the pair is the design’s.
Why the verbatimModuleSyntax‘s the requirements matter. The verbatimModuleSyntax‘s the requirements are the explicit’s, and the explicit’s is the intent’s. The import type‘s is the type-only’s, and the import‘s is the value’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax‘s the emit’s. The verbatimModuleSyntax‘s the emit’s is the verbatim’s, and the verbatim’s is the as-written’s.
// The source's:
import type { User } from './user';
import { greet } from './user';
// The emitted's (with the verbatimModuleSyntax):
import { greet } from './user';
// The type-only's is the erased's.
The import type { User } and the import { greet } are the source’s, and the source’s is the verbatim’s. The two are the pair, and the pair is the design’s.
Why the verbatimModuleSyntax‘s the emit’s matters. The verbatimModuleSyntax‘s the emit’s is the verbatim’s, and the verbatim’s is the predictable’s. The verbatimModuleSyntax‘s is the as-written’s, and the as-written’s is the clear’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax‘s the CommonJS’s. The verbatimModuleSyntax‘s the CommonJS’s is the import = require‘s, and the import = require‘s is the CommonJS’s.
// The verbatimModuleSyntax with the CommonJS:
import fs = require('fs'); // ✅ the CommonJS's
// import fs from 'fs'; // ❌ the ESM's in the CJS's
The import fs = require('fs') is the CommonJS’s, and the CommonJS’s is the specific’s. The two are the pair, and the pair is the design’s.
Why the verbatimModuleSyntax‘s the CommonJS’s matters. The verbatimModuleSyntax‘s the CommonJS’s is the import = require‘s, and the import = require‘s is the CJS’s. The import fs from 'fs'‘s is the ESM’s, and the ESM’s is the specific’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax‘s the esModuleInterop‘s. The verbatimModuleSyntax‘s the esModuleInterop‘s is the conflict’s, and the conflict’s is the choice’s.
// The verbatimModuleSyntax conflicts with the esModuleInterop:
{
"verbatimModuleSyntax": true,
"esModuleInterop": true // ⚠️ the conflict's
}
The verbatimModuleSyntax and the esModuleInterop are the conflict’s, and the conflict’s is the choice’s. The two are the pair, and the pair is the design’s.
Why the verbatimModuleSyntax‘s the esModuleInterop‘s matters. The verbatimModuleSyntax‘s the esModuleInterop‘s is the conflict’s, and the conflict’s is the choice’s. The verbatimModuleSyntax‘s is the verbatim’s, and the esModuleInterop‘s is the compatibility’s. The two are the pair, and the pair is the design’s.
The isolatedModules vs the verbatimModuleSyntax
The isolatedModules and the verbatimModuleSyntax are the pair’s, and the pair’s is the distinction’s.
The isolatedModules‘s the enforcement’s. The isolatedModules‘s the enforcement’s is the per-file’s, and the per-file’s is the transpiler’s.
{
"isolatedModules": true
}
The isolatedModules: true is the enforcement’s, and the enforcement’s is the per-file’s. The two are the pair, and the pair is the design’s.
The verbatimModuleSyntax‘s the emit’s. The verbatimModuleSyntax‘s the emit’s is the verbatim’s, and the verbatim’s is the as-written’s.
{
"verbatimModuleSyntax": true
}
The verbatimModuleSyntax: true is the emit’s, and the emit’s is the verbatim’s. The two are the pair, and the pair is the design’s.
The two’s the combination’s. The two’s the combination’s is the modern’s, and the modern’s is the standard’s.
{
"isolatedModules": true,
"verbatimModuleSyntax": true
}
The isolatedModules and the verbatimModuleSyntax are the combination’s, and the combination’s is the modern’s. The two are the pair, and the pair is the design’s.
Why the two’s the combination’s matters. The two’s the combination’s is the modern’s, and the modern’s is the standard’s. The isolatedModules‘s is the requirement’s, and the verbatimModuleSyntax‘s is the emit’s. The two are the pair, and the pair is the design’s.
The two’s the difference’s. The two’s the difference’s is the enforcement’s and the emit’s, and the emit’s is the verbatim’s.
| The aspect | The isolatedModules | The verbatimModuleSyntax |
|---|---|---|
| The purpose | The per-file’s | The verbatim’s emit’s |
| The error | The ambiguous’s | The emit’s mismatch’s |
| The require’s | The export type‘s | The import type‘s |
The const enum‘s | The error’s | The error’s |
The esModuleInterop‘s | The no-conflict’s | The conflict’s |
The table’s is the difference’s, and the difference’s is the design’s. The two are the pair, and the pair is the design’s.
Why the two’s the difference’s matters. The two’s the difference’s is the enforcement’s and the emit’s, and the emit’s is the verbatim’s. The isolatedModules‘s is the per-file’s, and the verbatimModuleSyntax‘s is the as-written’s. The two are the pair, and the pair is the design’s.
The type-only’s imports and exports
The type-only’s imports and exports are the explicit’s, and the explicit’s is the modern’s.
The import type‘s. The import type { User } from './user' is the type-only’s, and the type-only’s is the erased’s.
import type { User } from './user';
The import type { User } is the type-only’s, and the type-only’s is the erased’s. The two are the pair, and the pair is the design’s.
Why the import type matters. The import type is the explicit’s, and the explicit’s is the intent’s. The import type‘s is the type-only’s, and the type-only’s is the no-runtime’s. The two are the pair, and the pair is the design’s.
The export type‘s. The export type { User } from './user' is the type-only’s, and the type-only’s is the erased’s.
export type { User } from './user';
The export type { User } is the type-only’s, and the type-only’s is the erased’s. The two are the pair, and the pair is the design’s.
Why the export type matters. The export type is the explicit’s, and the explicit’s is the intent’s. The export type‘s is the type-only’s, and the type-only’s is the barrel’s. The two are the pair, and the pair is the design’s.
The inline’s type‘s. The import { type User, greet } from './user' is the inline’s, and the inline’s is the mixed’s.
import { type User, greet } from './user';
The import { type User, greet } is the inline’s, and the inline’s is the mixed’s. The two are the pair, and the pair is the design’s.
Why the inline’s type matters. The inline’s type is the mixed’s, and the mixed’s is the common’s. The import { type User, greet }‘s is the explicit’s, and the explicit’s is the intent’s. The two are the pair, and the pair is the design’s.
The per-specifier’s type‘s. The import { type User, type Role, greet } from './user' is the per-specifier’s, and the per-specifier’s is the explicit’s.
import { type User, type Role, greet } from './user';
The import { type User, type Role, greet } is the per-specifier’s, and the per-specifier’s is the explicit’s. The two are the pair, and the pair is the design’s.
Why the per-specifier’s type matters. The per-specifier’s type is the explicit’s, and the explicit’s is the granular’s. The type User‘s is the type-only’s, and the greet‘s is the value’s. The two are the pair, and the pair is the design’s.
The import type * as Types‘s. The import type * as Types from './types' is the namespace’s, and the namespace’s is the type-only’s.
import type * as Types from './types';
The import type * as Types is the namespace’s, and the namespace’s is the type-only’s. The two are the pair, and the pair is the design’s.
Why the import type * as Types matters. The import type * as Types is the namespace’s, and the namespace’s is the type-only’s. The Types.User‘s is the type’s, and the type’s is the erased’s. The two are the pair, and the pair is the design’s.
The export { type User }‘s. The export { type User } is the inline’s, and the inline’s is the mixed’s.
export { type User, greet } from './user';
The export { type User, greet } is the inline’s, and the inline’s is the mixed’s. The two are the pair, and the pair is the design’s.
Why the export { type User } matters. The export { type User } is the inline’s, and the inline’s is the mixed’s. The type User‘s is the type-only’s, and the greet‘s is the value’s. The two are the pair, and the pair is the design’s.
The common’s errors and the fixes
The common’s errors are the specific’s, and the specific’s is the fix’s.
The error 1: the TS1205‘s. The TS1205‘s is the re-export’s, and the re-export’s is the type-only’s.
// The error:
export { User } from './user';
// error TS1205: Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'.
// The fix:
export type { User } from './user';
The export { User } from './user' is the error’s, and the error’s is the TS1205‘s. The export type { User } is the fix’s, and the fix’s is the explicit’s. The two are the pair, and the pair is the design’s.
Why the error 1 matters. The error 1 is the re-export’s, and the re-export’s is the barrel’s. The export type‘s is the fix’s, and the fix’s is the explicit’s. The two are the pair, and the pair is the design’s.
The error 2: the TS2748‘s. The TS2748‘s is the const enum’s, and the const enum’s is the cross-file’s.
// The error:
const enum Color { Red }
// error TS2748: Cannot access ambient const enums when 'isolatedModules' is enabled.
// The fix:
enum Color { Red }
// Or the preserveConstEnums:
// "preserveConstEnums": true
The const enum Color { Red } is the error’s, and the error’s is the TS2748‘s. The enum Color { Red } is the fix’s, and the fix’s is the plain’s. The two are the pair, and the pair is the design’s.
Why the error 2 matters. The error 2 is the const enum’s, and the const enum’s is the inlining’s. The preserveConstEnums‘s is the fix’s, and the fix’s is the runtime’s. The two are the pair, and the pair is the design’s.
The error 3: the TS1209‘s. The TS1209‘s is the ambient’s, and the ambient’s is the module’s.
// The error:
declare global { ... }
// error TS1209: Ambient modules cannot be nested in other modules or namespaces.
// The fix:
export {};
declare global { ... }
The declare global { ... } is the error’s, and the error’s is the TS1209‘s. The export {}; is the fix’s, and the fix’s is the module’s. The two are the pair, and the pair is the design’s.
Why the error 3 matters. The error 3 is the ambient’s, and the ambient’s is the module’s. The export {};‘s is the fix’s, and the fix’s is the explicit’s. The two are the pair, and the pair is the design’s.
The error 4: the TS1284‘s. The TS1284‘s is the export =‘s, and the export =‘s is the specific’s.
// The error:
export = SomeValue;
// error TS1284: An 'export =' declaration must reference a value when 'isolatedModules' is enabled.
// The fix:
// The use of the value's, not the type's.
The export = SomeValue is the error’s, and the error’s is the TS1284‘s. The fix’s is the value’s, and the value’s is the specific’s. The two are the pair, and the pair is the design’s.
Why the error 4 matters. The error 4 is the export =‘s, and the export =‘s is the CJS’s. The fix’s is the value’s, and the value’s is the specific’s. The two are the pair, and the pair is the design’s.
The error 5: the TS1479‘s. The TS1479‘s is the CJS’s and the ESM’s, and the ESM’s is the import’s.
// The error:
import { something } from './cjs-module';
// error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module.
// The fix:
// The await import()'s, or the .mjs's.
The import { something } from './cjs-module' is the error’s, and the error’s is the TS1479‘s. The await import()‘s is the fix’s, and the fix’s is the dynamic’s. The two are the pair, and the pair is the design’s.
Why the error 5 matters. The error 5 is the CJS’s and the ESM’s, and the ESM’s is the import’s. The await import()‘s is the fix’s, and the fix’s is the modern’s. The two are the pair, and the pair is the design’s.
Complete Example Session
// ============================================
// PART 1: THE ISOLATED MODULES'S ERRORS
// ============================================
// tsconfig.json
{
"compilerOptions": {
"isolatedModules": true
}
}
// The TS1205's:
export { User } from './user';
// ❌ Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'.
// The fix:
export type { User } from './user'; // ✅
// ============================================
// PART 2: THE VERBATIM MODULE SYNTAX'S ERRORS
// ============================================
// tsconfig.json
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
// The error:
import { User } from './user'; // ❌ the type-only's is the not-marked's
// The fix:
import type { User } from './user'; // ✅
// ============================================
// PART 3: THE INLINE'S TYPE
// ============================================
import { type User, greet } from './user';
// The User's is the type's, and the greet's is the value's.
// ============================================
// PART 4: THE EXPORT TYPE
// ============================================
export type { User } from './user';
export { greet } from './user';
// ============================================
// PART 5: THE PER-SPECIFIER'S
// ============================================
import { type User, type Role, greet } from './user';
// ============================================
// PART 6: THE CONST ENUM'S
// ============================================
// The error:
const enum Color { Red } // ❌ the isolatedModules's error
// The fix:
enum Color { Red } // ✅
// Or:
// "preserveConstEnums": true
// ============================================
// PART 7: THE AMBIENT'S
// ============================================
// The error:
declare global { interface Window { myApp: App } } // ❌
// The fix:
export {};
declare global { interface Window { myApp: App } } // ✅
// ============================================
// PART 8: THE COMBINATION'S
// ============================================
// tsconfig.json
{
"compilerOptions": {
"isolatedModules": true,
"verbatimModuleSyntax": true,
"module": "nodenext",
"moduleResolution": "nodenext"
}
}
// ============================================
// PART 9: THE EMITTED'S
// ============================================
// The source's:
import type { User } from './user';
import { greet } from './user';
// The emitted's (with the verbatimModuleSyntax):
import { greet } from './user';
// The type-only's is the erased's.
// ============================================
// PART 10: WHAT NOT TO DO
// ============================================
// Don't use the ambiguous's import
import { User } from './user'; // ❌ the type-only's // ⚠️
// Don't forget the export type in the barrel
export { User } from './user'; // ❌ the TS1205's // ⚠️
// Don't use the const enum
const enum Color { Red } // ❌ the TS2748's // ⚠️
// Don't forget the export {} in the ambient's
declare global { ... } // ❌ the TS1209's // ⚠️
// Don't combine the verbatimModuleSyntax with the esModuleInterop
{
"verbatimModuleSyntax": true,
"esModuleInterop": true // ⚠️ the conflict's
}
// Don't forget the import type for the types
import { User } from './user'; // ❌ the explicit's is the required's│// ⚠️
The ten parts cover the isolated modules’s errors, the verbatim module syntax’s errors, the inline’s type, the export type, the per-specifier’s, the const enum’s, the ambient’s, the combination’s, the emitted’s, and the anti-patterns.
Quick Reference
The isolatedModules‘s Errors
| Error | Cause | Fix |
|---|---|---|
TS1205 | The type-only’s re-export’s | The export type |
TS2748 | The const enum’s | The enum‘s |
TS1209 | The ambient’s | The export {} |
TS1284 | The export =‘s | The value’s |
TS1479 | The CJS/ESM’s | The await import() |
The verbatimModuleSyntax‘s Requirements
| The source | The required’s |
|---|---|
| The type’s import | The import type |
| The type’s export | The export type |
| The value’s import | The plain’s import |
| The value’s export | The plain’s export |
The Type-Only’s Forms
| Form | Purpose |
|---|---|
import type { User } | The named’s type-only |
import type Default | The default’s type-only |
import type * as Types | The namespace’s type-only |
import { type User, greet } | The inline’s mixed |
export type { User } | The re-export’s type-only |
export { type User, greet } | The inline’s mixed |
The Two’s the Comparison’s
| Aspect | The isolatedModules | The verbatimModuleSyntax |
|---|---|---|
| The purpose | The per-file’s | The verbatim’s emit’s |
| The error | The ambiguous’s | The emit’s mismatch’s |
| The require’s | The export type‘s | The import type‘s |
The const enum‘s | The error’s | The error’s |
The esModuleInterop‘s | The no-conflict’s | The conflict’s |
The preserveConstEnums‘s
| Value | Behavior |
|---|---|
false (default) | The const enum’s is the inlined’s |
true | The const enum’s is the emitted’s |
The verbatimModuleSyntax‘s the esModuleInterop‘s
| Combination | Result |
|---|---|
Both true | The conflict’s |
verbatimModuleSyntax: true | The ESM’s is the explicit’s |
esModuleInterop: true | The CJS’s is the compatible’s |
Best Practices
✅ Do This:
// Use the import type for the types
import type { User } from './user'; // ✅
// Use the export type for the re-exports
export type { User } from './user'; // ✅
// Use the inline's type for the mixed
import { type User, greet } from './user'; // ✅
// Use the plain's enum instead of the const enum
enum Color { Red } // ✅
// Use the export {} in the ambient's
export {};
declare global { ... } // ✅
// Use the two together
{
"isolatedModules": true,
"verbatimModuleSyntax": true
} // ✅
// Use the preserveConstEnums if the const enum is required
{
"isolatedModules": true,
"preserveConstEnums": true
} // ✅
❌ Don’t Do This:
// Don't use the ambiguous's import
import { User } from './user'; // ❌ // ⚠️
// Don't forget the export type in the barrel
export { User } from './user'; // ❌ the TS1205's // ⚠️
// Don't use the const enum
const enum Color { Red } // ❌ the TS2748's // ⚠️
// Don't forget the export {} in the ambient's
declare global { ... } // ❌ the TS1209's // ⚠️
// Don't combine the verbatimModuleSyntax with the esModuleInterop
{
"verbatimModuleSyntax": true,
"esModuleInterop": true // ⚠️ the conflict's
}
// Don't use the type's without the type marker
import { User } from './user'; // ❌ the explicit's is the required's│// ⚠️
Common Pitfalls
| Pitfall | Problem | Solution |
|---|---|---|
| The ambiguous’s import | The transpiler’s error | The import type |
The missing export type | The TS1205 | The export type |
The const enum | The TS2748 | The enum or the preserveConstEnums |
| The ambient’s | The TS1209 | The export {} |
The verbatimModuleSyntax + the esModuleInterop | The conflict | The pick the one’s |
| The type-only’s unmarked | The error | The explicit’s |
| The barrel’s type | The TS1205 | The export type |
| The per-specifier’s | The verbose | The all’s import type |
Real-World Examples
1. The type-only’s import
import type { User } from './user';
2. The inline’s type
import { type User, greet } from './user';
3. The export type
export type { User } from './user';
4. The per-specifier’s
import { type User, type Role, greet } from './user';
5. The barrel
export type { User, Role } from './types';
export { greet } from './greet';
6. The isolatedModules
{ "compilerOptions": { "isolatedModules": true } }
7. The verbatimModuleSyntax
{ "compilerOptions": { "verbatimModuleSyntax": true } }
8. The combination
{
"compilerOptions": {
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}
9. The preserveConstEnums
{ "compilerOptions": { "preserveConstEnums": true } }
10. The export {} for the ambient’s
export {};
declare global { ... }
Visual: The isolatedModules
┌──────────────────────────────────────────────┐
│ THE TRANSPILER'S (the Babel, the esbuild) │
│ The file-by-file's │
│ The no-type's information's │
│ The import { User }'s is the ambiguous's │
│ │
├──────────────────────────────────────────────┤
│ THE isolatedModules'S │
│ The per-file's is the requirement's │
│ The explicit's is the type's │
│ The TS1205's, the TS2748's, the TS1209's │
│ │
│ The explicit's is the safe's. │
│ │
└──────────────────────────────────────────────┘
Visual: The verbatimModuleSyntax
┌──────────────────────────────────────────────┐
│ THE SOURCE'S │
│ import type { User } from './user'; │
│ import { greet } from './user'; │
│ │
│ │ The compiler │
│ ▼ │
│ │
│ THE EMITTED'S │
│ import { greet } from './user'; │
│ (The type-only's is the erased's.) │
│ │
│ The verbatim's is the as-written's. │
│ │
└──────────────────────────────────────────────┘
Visual: The Type-Only’s Forms
┌──────────────────────────────────────────────┐
│ import type { User } from './user'; │
│ The named's type-only's │
│ │
│ import type Default from './default'; │
│ The default's type-only's │
│ │
│ import type * as Types from './types'; │
│ The namespace's type-only's │
│ │
│ import { type User, greet } from './user'; │
│ The inline's mixed's │
│ │
│ import { type User, type Role, greet } │
│ The per-specifier's │
│ │
│ export type { User } from './user'; │
│ The re-export's type-only's │
│ │
│ export { type User, greet } from './user'; │
│ The inline's export's │
│ │
└──────────────────────────────────────────────┘
Visual: The Two’s the Comparison’s
┌──────────────────────────────────────────────┐
│ THE isolatedModules'S │
│ The per-file's is the requirement's │
│ The TS1205's, the TS2748's, the TS1209's │
│ The export type's is the required's │
│ │
├──────────────────────────────────────────────┤
│ THE verbatimModuleSyntax'S │
│ The verbatim's is the emit's │
│ The import type's is the required's │
│ The esModuleInterop's is the conflict's │
│ │
│ The two's is the pair's, and the pair's is │
│ the modern's. │
│ │
└──────────────────────────────────────────────┘
Visual: The const enum‘s
┌──────────────────────────────────────────────┐
│ THE const enum's: │
│ The inlining's, the no-runtime's │
│ The isolatedModules's error's │
│ │
├──────────────────────────────────────────────┤
│ THE FIXES: │
│ The enum's (the plain's) │
│ The preserveConstEnums: true │
│ │
│ The const enum's is the fast's, and the │
│ fast's is the tradeoff's. │
│ │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
The isolatedModules | The per-file’s |
The verbatimModuleSyntax | The verbatim’s emit’s |
The import type | The type-only’s import |
The export type | The type-only’s export |
The inline’s type | The mixed’s |
The TS1205 | The re-export’s error |
The TS2748 | The const enum’s error |
The TS1209 | The ambient’s error |
The preserveConstEnums | The const enum’s fix |
The esModuleInterop‘s | The conflict’s with the verbatimModuleSyntax |
Key takeaways:
- The per-file transpilation is the modern toolchain’s requirement — the Babel, the esbuild, the SWC, the Vite transpile one file at a time, and they cannot determine the type’s vs the value’s
- The
isolatedModulesenforces the per-file’s rules — it catches the ambiguous’s re-exports, theconst enum‘s, the ambient’s, and theexport =‘s - The
verbatimModuleSyntaxmakes the emit match the source — it requires the explicit’simport typeandexport type, and it is incompatible with theesModuleInterop‘s shim - The
import typeand theexport typeare the explicit’s — theimport type { User }is the type-only’s, and theexport type { User }is the re-export’s - The inline’s
typeis the mixed’s — theimport { type User, greet }imports both the type and the value in one statement - The
const enum‘s is the error’s under theisolatedModules— theenum‘s or thepreserveConstEnums: true‘s is the fix’s - The ambient’s requires the
export {}‘s — thedeclare global‘s in the module’s needs theexport {}to be the module’s - The two options are the pair’s — the
isolatedModulesrequires the explicit’s, and theverbatimModuleSyntaxmakes the emit’s match - The
verbatimModuleSyntax‘s conflicts with theesModuleInterop‘s — the two cannot be combined, and the choice is the project’s - The errors are the specific’s — the
TS1205, theTS2748, theTS1209, theTS1284, theTS1479are the common’s, and the fixes are the specific’s
Remember: The isolatedModules and the verbatimModuleSyntax are the modern toolchain’s requirements. The per-file transpilation cannot determine the type’s vs the value’s, so the explicit’s type markers are the requirement’s. The import type and the export type are the explicit’s, and the verbatimModuleSyntax makes the emit match the source. The two are the pair, and the pair is the modern’s. The errors are the specific’s, and the fixes are the explicit’s.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!