Fix: TypeScript 'isolatedModules' Error When Re-exporting Types

beginner🔵 TypeScript2026-06-25| Vite, esbuild, Next.js, or any TypeScript project with isolatedModules enabled in tsconfig.json.

Error Message

Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.
#typescript#isolatedModules#vite#esbuild#tsconfig

The Problem ContextI recently migrated a mid-sized React codebase—roughly 45,000 lines of code—from Webpack to Vite. The transition was mostly seamless until I touched the 'barrel files.' These index.ts files aggregate our exports, but they caused the Vite dev server to throw a fit. The console immediately flagged this error:

Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'.

This happens because Vite uses esbuild for transpilation. Unlike the standard TypeScript compiler (tsc), which analyzes your entire project graph, esbuild processes each file in total isolation. It is incredibly fast—often 10x to 100x faster than tsc—but it has a blind spot. It cannot tell if an exported name is a JavaScript constant or a TypeScript interface that should be erased during the build.

The Debug ProcessThe root of the issue lies in your tsconfig.json. If you are using modern build tools, you likely have this setting enabled:

{
  "compilerOptions": {
    "isolatedModules": true
  }
}

When isolatedModules is active, TypeScript prevents you from using patterns that a single-file transpiler can't handle. Re-exporting a type using standard syntax is one of those forbidden patterns. Take this common example in a src/types/index.ts file:

// src/types/user.ts
export interface User {
  id: string;
  name: string;
}

// src/types/index.ts
export { User } from './user'; // <-- This triggers the error

The transpiler sees export { User } and gets confused. It doesn't know whether to generate code for a runtime object or to delete the line entirely because User is just a type.

The Solutions### 1. Use explicit 'export type'The most straightforward fix is to tell the compiler exactly what you are doing. This syntax was introduced in TypeScript 3.8 and explicitly marks the export for erasure.

// Change this:
export { User } from './user';

// To this:
export type { User } from './user';

2. Mixed exports (TypeScript 4.5+)If you need to export a component and its corresponding type from the same file, you don't need two separate lines. Inline type modifiers make this much cleaner.

// src/components/index.ts
export { 
  Button, 
  type ButtonProps 
} from './Button';

3. Separate imports and exportsFor teams stuck on older TypeScript versions or those who prefer a more verbose style, you can split the operation. Import the type first, then export it separately.

import { User } from './user';
export type { User };

VerificationDon't just rely on the Vite HMR (Hot Module Replacement) to tell you it's fixed. I always run a manual type check in the terminal to be certain:

npx tsc --noEmit

The --noEmit flag is perfect here. It performs a full type check without generating any .js files, which is exactly what you want when Vite or esbuild is handling the actual bundling.

Lessons Learned- Speed requires clarity: Tools like esbuild and SWC are fast because they skip deep type analysis. We must use explicit syntax to help them navigate our code.- Keep isolatedModules on: If your build tool doesn't use tsc, keep this flag enabled. It acts as an early warning system, preventing production build failures.- Adopt 'import type' by default: I've started using import type for all interfaces. It makes the code's intent obvious to both the compiler and my teammates.

Related Error Notes