Introduction
TypeScript adds a type system on top of JavaScript, then compiles down to plain JavaScript that runs anywhere JavaScript already does. The types exist purely to help you and your editor catch mistakes before the code runs — by the time it's compiled, every type annotation is gone.
What TypeScript actually is
TypeScript is three things bundled together, and it helps to keep them apart in your head:
- A language — JavaScript's syntax plus extra syntax for describing types (
: string,interface,<T>and so on). Every valid JavaScript file is already valid TypeScript syntax. - A type checker — a program that reads your code, works out what kind of value each expression holds, and reports anywhere those don't line up.
- A compiler —
tsc, which removes the type syntax and writes out ordinary.jsfiles that browsers and Node.js can run.
The checker is what you'll interact with most. It powers the red squiggles, autocomplete and "go to definition" in editors like VS Code — even in plain JavaScript files, VS Code is quietly running TypeScript's checker behind the scenes.
A plain JavaScript problem
In JavaScript, nothing stops you from calling a function with the wrong kind of value. The mistake only shows up once the code actually runs:
function greet(name) { return "Hello, " + name.toUpperCase() + "!"; } console.log(greet(42));
Uncaught TypeError: name.toUpperCase is not a function
Nothing about the code above looked wrong until it ran — 42 is a valid argument as far as JavaScript is concerned, right up until .toUpperCase() is called on it. In a large app, that line might only run when a rare button is clicked, so the bug can sit unnoticed for months.
The same code in TypeScript
Adding a type annotation to the parameter tells the compiler exactly what's allowed, so the mistake is caught before the program ever runs:
function greet(name: string) { return "Hello, " + name.toUpperCase() + "!"; } console.log(greet(42));
error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
name: string is a type annotation — it tells the compiler that name must always be a string. Running tsc greet.ts catches the mismatch immediately, instead of letting it become a runtime crash.
Compiling to JavaScript
Once the types check out, tsc strips every type annotation and produces ordinary JavaScript:
function greet(name: string): string { return "Hello, " + name.toUpperCase() + "!"; } console.log(greet("maya"));
Hello, MAYA!
function greet(name) { return "Hello, " + name.toUpperCase() + "!"; } console.log(greet("maya"));
Compare the two files: the logic is identical, only the : string annotations have disappeared. This is called type erasure, and it's the single most important idea in this course.
Try it yourself
The editor below compiles your TypeScript in the browser and runs the result. Change the name, add another console.log, or call greet twice:
Why teams adopt it
- Earlier feedback. Typos in property names, wrong argument orders and forgotten
nullchecks show up while you type. - Safer refactoring. Rename a property and the compiler lists every place that still uses the old name.
- Living documentation. A signature like
function charge(amountCents: number, currency: "USD" | "EUR")tells the next developer exactly what's expected, and unlike a comment it can't go stale. - Better tooling. Autocomplete knows which properties exist on every object.
The trade-off is an extra build step and some time spent describing your data. For anything larger than a small script, most teams find that cost pays for itself quickly.