Is the TypeScript Compiler a True Compiler or Just a Transpiler?
“The TypeScript Compiler It is not a compiler in the classical sense. A classical compiler turns source into machine code. The TypeScript compiler turns TypeScript into JavaScript. It is a source‑to‑source transformer, a transpiler, a type eraser. But that undersells it. The TypeScript compiler is a verifier. It holds an entire type system in memory—structural, not nominal. It assigns types to every expression, every variable, every function return, before it ever emits a single line of JavaScript. If the types do not align, it reports errors. By default it may still emit JavaScript (to allow gradual migration), but in a strict build pipeline it is configured to halt without output, stopping the build. The types are a fiction. They exist only at compile time. At runtime, they vanish. The emitted JavaScript contains no trace of them. The compiler’s greatest work is invisible to the machine that runs the code. The compiler itself is a pipeline: Scanner → tokens. Parser → AST (Abstract Syntax Tree), including type annotations as part of the tree. Binder → links identifiers to their declarations. Type Checker → the heart. It walks the AST, infers types, checks assignability, resolves generics, applies narrowing. It maintains a control flow graph to understand type guards. It is a theorem prover over a structural type algebra, with unions, intersections, literal types, and conditional types. It can exhaustiveness‑check discriminated unions. It can model deeply recursive type constructions. Emitter → takes the AST and produces JavaScript, stripping types, downleveling modern syntax to older ECMAScript versions based on target. The entire process is deterministic, but the type checker can feel like magic. It follows strict rules, yet its inferences can surprise even experts. It is simultaneously a safety net and a puzzle. The compiler runs in a separate process from the browser, typically invoked by a build tool (tsc, esbuild, swc, babel with TypeScript plugin). Some tools only strip types without checking (like esbuild or swc used via Vite). That is faster but trusts that the developer ran tsc --noEmit separately. The official compiler is slower but authoritative. Its output is plain JavaScript. That JavaScript will then be consumed by the JavaScript engine. The compiler’s only lasting artifact is the code, and a set of declaration files (.d.ts) that describe the shapes of the module for other TypeScript consumers. These are type‑level contracts, not executable code. In essence: the TypeScript compiler is a guardian that never follows the code into battle. It inspects the blueprints, declares them sound, and then steps aside.”
Summary
The TypeScript compiler functions as a source‑to‑source transformer (transpiler) that also performs full type checking, maintaining a structural type system in memory before emitting plain JavaScript. It follows the pipeline of scanner, parser, binder, type checker, and emitter, and can be configured to halt on type errors, producing declaration files for downstream TypeScript consumption. Thus, the description of it as a verifier and transpiler that erases types at runtime is correct.
Sources 60 searched
- Transpilers | ts-node
What is the difference between a compiler and a transpiler? For our purposes, a compiler implements TypeScript's API and can perform typechecking. A third-party transpiler does not.
- TypeScript: Documentation - What is a tsconfig.json
compilerOptions": { " module": "commonjs", " noImplicitAny": true, " removeComments": true, " preserveConstEnums": true, " sourceMap": true · }, " files": [ "core.ts", "sys.ts", "types.ts", "scanner.ts", "parser.ts", "utilities.ts", "binder.ts", "checker.ts", "emitter.ts", "program.ts", "commandLineParser.ts", "tsc.ts", "diagnosticInformationMap.generated.ts" ] } Using the include and exclude properties ·
- compiler construction - Compiling vs Transpiling - Stack Overflow
2020-11-10T15:59:07.923Z+00:00 ... Microsoft writes that the TypeScript compiler transpiles TypeScript source code to JavaScript: code.visualstudio.com/docs/typescript/… 2022-08-10T16:28:19.04Z+00:00
- Typescript Transpiler Explained | daily.dev
It converts Typescript into plain ... Transpilation vs. Compilation: Transpilation transforms code within the same level of abstraction, whereas compilation converts to a lower-level code....
- Behind the Scenes of TypeScript: Understanding the Lexer, Parser, Binder, Checker And Emitter | by jyoti jingar | Medium
Understanding TypeScript internals helps developers debug better, write cleaner code, and explain concepts with confidence. This article walks through the complete TypeScript compilation workflow — from lexical analysis and parsing to binding, type checking, transformation, and final JavaScript emission.
- Behind the Scenes of TypeScript: Understanding the Lexer, Parser, Binder, Checker, and Emitter - DEV Community
The Lexer is the first stage of the compiler. ... Why important: It simplifies code for the parser. Parser converts tokens into an AST (Abstract Syntax Tree). ... VariableStatement └─ VariableDeclaration ├─ name: x ├─ type: number └─ initializer: 10 · Why important: All further operations (type checking, transformation) run on this AST. ... Why important: The type checker needs this to resolve identifiers.
- Typescript is *not* a compile-time language. It’s developer-time … | by Michael Michailidis | Medium
Things are changing, of course, and Bun is created to run typescript natively, but traditionally all typescript features dissapeared before the code was executed, removing any type-safety that might have been desired. This reality has given typescript it’s designation as a “compile time” rather than “runtime” language.
- TypeScript is surprisingly ok for compilers | Hacker News
The fact that Functions are Objects that can have properties/methods is supremely undervalued · Are there other languages that do this so nicely? It's the perfect blend of OO and functional
- TypeScript is Surprisingly OK for Compilers
Our types are really simple, we could have gone with type Type = "Int" | "Bool", but lets do this a bit more enterprisy! We define separate types for integer and boolean types. As these types are singletons, we also provide canonical definitions. And here is another TypeScript-ism.