Lesson 67 of 80
tsc type-checks your whole program at once, but esbuild, SWC, and Babel transpile one file at a time with zero type information — these flags make tsc reject anything that would break under that faster, blinder pipeline.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
tsc reads every file in your program together. It knows what every import resolves to, whether a name is a type or a value, and what every enum member actually equals. A single-file transpiler — esbuild, SWC, Babel's TypeScript preset — does none of that. It strips types from one file at a time, with no visibility into any other file, because that's exactly what makes it fast. Most real projects now use one of these for the actual build, and use tsc only to type-check — which means code that compiles fine under tsc can still silently break the faster tool it never actually ran through.
isolatedModules closes that gap: it makes tsc itself refuse to compile anything that a per-file transpiler couldn't safely handle alone.
// types.ts
export interface User {
id: string;
name: string;
}
export const ADMIN_ROLE = "admin";
// api.ts
export { User, ADMIN_ROLE } from "./types";
tsc compiles api.ts knowing User is a type (erase it, emit nothing) and ADMIN_ROLE is a value (keep it, emit a real export). esbuild processing api.ts alone has no idea what ./types exports — it can't open that file and check. With isolatedModules on, tsc flags this re-export as ambiguous and forces you to be explicit:
export type { User } from "./types";
export { ADMIN_ROLE } from "./types";
Now export type tells a blind, per-file transpiler exactly what to do — drop it — without needing to look anywhere else.
const enum hits the same wall from a different angle. tsc normally inlines every Direction.Up reference to its literal value (0) at every call site across the whole program — that's the entire point of const enum, zero runtime object. A transpiler processing the consuming file alone can't do that inlining, because the enum's declaration lives in a file it never opens. isolatedModules treats const enum as unsafe across file boundaries for exactly this reason.
verbatimModuleSyntax: no more guessingEven with isolatedModules, tsc still tries to help: an import used only in type positions gets silently dropped from the output, even without import type. verbatimModuleSyntax — the newer, stricter flag — turns that guessing off entirely. Every import and export is emitted verbatim, exactly as written, no inference. If something is type-only, you write import type yourself; if you don't, it survives into the compiled JavaScript as a real import, which can then fail at runtime if ./types has no matching runtime export at all.
tsc itself can compile. They exist to reject code that would silently misbehave under a different tool — the one that actually runs at build time in most modern setups.import type / export type, not a redesign. The errors look alarming but are nearly always solved by being explicit about which names are types.const enum is worth avoiding in shared library code entirely, not just working around — regular enum (or a plain object with as const) has no cross-file inlining requirement and is safe everywhere."Why would tsc --noEmit pass but the actual esbuild build break?" is a real, specific senior-level question, because it tests whether someone understands that type-checking and compiling are two separate steps in a modern toolchain — and that tsc only protects the second step if you've told it to, via isolatedModules or verbatimModuleSyntax.