Skip to main content

Basics

What is TypeScript?

TypeScript is a superset of JavaScript created by Microsoft.

  • "Superset" means it builds on top of JavaScript, adding extra features.
  • It is not a completely new language — any valid JavaScript code is also valid TypeScript code.
  • The most important feature it adds is static typing.

TypeScript code cannot run directly in browsers or Node.js. It needs to be compiled (transpiled-source(ts) to source(js) compilation) into JavaScript using the TypeScript compiler (tsc).

Why use TypeScript?

Static Typing

  • In JavaScript, variables can hold any type of value, which often leads to runtime/unexpected errors.
  • TypeScript lets you declare types for variables, function parameters, and return values.
  • This allows catching errors at compile-time instead of at runtime.

Example (JavaScript problem):

function add(a, b) {
return a + b;
}

console.log(add(5, 10)); // 15 ✅
console.log(add(5, "10")); // "510" ❌ (unexpected)

Example (TypeScript solution):

function add(a: number, b: number): number {
return a + b;
}

console.log(add(5, 10)); // 15 ✅
console.log(add(5, "10")); // ❌ Compile-time error

Better IDE Support (IntelliSense & Autocomplete)

  • TypeScript provides better code suggestions, hints, and autocompletion in editors like VS Code.
  • This makes development faster and reduces mistakes.

Improved Code Quality and Maintainability

  • Large projects with many developers benefit from TypeScript because types make the code more predictable and self-documenting.
  • Helps new developers understand the codebase quickly.

Modern JavaScript Features with Backward Compatibility

  • TypeScript supports new JavaScript features (ES6+) and compiles them into older JavaScript that works on older browsers.

Error Detection Before Execution

  • With TypeScript, many bugs are caught at compile-time, reducing runtime crashes.

Self Hosting

A programming language’s compiler or interpreter is written in the same language it is compiling.

So, a self-hosting compiler can “compile itself.”

This usually doesn’t happen right away — because when a language is brand new, you can’t write its compiler in that language (since you don’t yet have a compiler to translate it). So the very first compiler is usually written in another language (like C, JavaScript, or assembly).

Once the language is stable enough, developers rewrite the compiler in that same language.

Real Examples

C Language

  • The very first C compiler was written in assembly.
  • Once C was reliable, they rewrote the compiler in C itself.
  • From then on, C could compile its own compiler → self-hosting.

TypeScript

  • The very first TypeScript compiler was written in JavaScript (2012).
  • Later, the compiler was rewritten in TypeScript.
  • That compiler was compiled once using the old JavaScript compiler.
  • After that, TypeScript could compile its own compiler → self-hosting.

Why Self-Hosting?

  1. Dogfooding → The language proves it’s strong enough to build large, complex software (like its own compiler).
  2. Maintainability → Compiler developers get the same language features as normal developers.
  3. Better Testing → Every change to the compiler tests the language itself.
  4. Trust & Adoption → If a compiler is written in the language itself, it shows confidence and maturity.

Bootstrapping Steps

  1. The Very First Compiler (2012)

    • Written in JavaScript.
    • Its job: take .ts code and produce .js output.
    • At this point, TypeScript itself was too new and unstable to be used for building its own compiler.
  2. Bootstrapping (Self-Hosting Transition)

    • Once TypeScript became stable enough, the team rewrote the compiler in TypeScript.
    • But here’s the trick:
      • The new compiler source code was in TypeScript (.ts).
      • To run it, they still needed the old JavaScript-based compiler to compile it once into JavaScript.
      • After that, the newly compiled version could take over future builds.

    This is the self-hosting loop.

  3. Current Compiler

    • Today’s compiler (tsc) is written in TypeScript itself.
    • Each new version of TypeScript is compiled using the previous version’s compiler.
    • The result is distributed as JavaScript (so it can run on Node.js, since Node doesn’t understand TypeScript directly).

So yes — the current compiler is ultimately built on top of that very first JavaScript compiler, which “bootstrapped” the process.

TypeScript Compiler

The TypeScript Compiler (tsc) is the tool that takes TypeScript code (.ts or .tsx files) and compiles (or transpiles) it into plain JavaScript, which browsers or Node.js can run.

Since browsers don’t understand TypeScript directly, the compiler ensures all TypeScript features (types, interfaces, enums, decorators, etc.) are converted into valid JavaScript.

Key Responsibilities of TypeScript Compiler

  1. Type Checking

    • Ensures variables, function arguments, and return values match declared types.
    • Prevents common bugs during development.
  2. Transpiling

    • Converts modern TypeScript/JavaScript features into target JavaScript versions (e.g., ES5, ES6, ES2020).
  3. Configuration via tsconfig.json

    • Developers can customize compilation: target JavaScript version, module system (CommonJS, ESModules), include/exclude files, strictness, etc.
  4. Incremental Builds

    • The TypeScript compiler compiles all files in your project every time — even if only one file was changed. This can be slow for big projects.
    • With incremental builds (--watch mode or "incremental": true in tsconfig.json), TypeScript remembers what was already compiled and only recompiles changed files (and their dependencies).
  5. Error Reporting

    • Shows compilation errors with line numbers and hints.

Compiler Architecture

The TypeScript Compiler (tsc) is built in TypeScript itself, and its architecture can be broken into three main stages:

class Person {
constructor(public name: string) {}
greet(): string {
return `Hello, ${this.name}`;
}
}

let p = new Person("Alice");
console.log(p.greet());

1. Parsing

  • The compiler reads your .ts source code.
  • It breaks it into tokens (keywords, identifiers, operators, literals, etc.) and builds an Abstract Syntax Tree (AST) — a tree structure representing the code.
SourceFile
├─ ClassDeclaration: Person
│ ├─ Constructor
│ │ └─ Parameter: name: string
│ └─ Method: greet(): string
└─ VariableDeclaration: p: Person

Parsing does no type checking yet — it just understands the structure of your code.

2. Binding & Type Checking

  • The compiler now binds identifiers (variables, classes, functions) to their declarations using a symbol table.
  • It performs type checking:
    • Ensures variables, parameters, and return values match their declared types.
    • Checks function calls, classes, interfaces, generics, etc.
let p: number = new Person("Alice"); // ❌ Error
  • new Person("Alice") returns a Person object.
  • p expects a number.
  • TypeScript throws a compile-time error:
Type 'Person' is not assignable to type 'number'.

This prevents runtime errors before the code even runs.

3. Emit (Code Generation)

  • If no blocking errors exist, the compiler converts the AST into plain JavaScript.
  • Type annotations are removed because JavaScript doesn’t understand them.
  • The compiler may also target different JS versions (ES5, ES6, etc.) and module systems (CommonJS, ES Modules).

Input (TypeScript):

class Person {
constructor(public name: string) {}
greet(): string {
return `Hello, ${this.name}`;
}
}

let p = new Person("Alice");
console.log(p.greet());

Output (JavaScript ES5):

var Person = /** @class */ (function () {
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return "Hello, " + this.name;
};
return Person;
})();
var p = new Person("Alice");
console.log(p.greet());

The public name: string annotation is removed, but the code still works in any JavaScript environment.

If we run with:

tsc --noEmitOnError

No JS files will be produced even after there have an error.

If we allow emit:

tsc

We’ll still get compiled JavaScript (types removed), but the error will be shown in the console.