How TypeScript works
JavaScript plus type annotations: what the annotations are for, why the browser never sees them, and what the preview does with your code.
JavaScript with a promise
TypeScript is JavaScript with types written into it. The types describe what a value is meant to be — string, number, boolean — and they sit in the code next to the names, not in a comment off to the side.
That is the whole idea. Every line of JavaScript is already valid TypeScript; adding types does not change what the program does, it changes what the program says about itself.
The same program, with the promise written down
const name: string = "Ada";
function greet(who: string): string {
return "Hello, " + who;
}
console.log(greet(name));Checked first, erased before it runs
Browsers do not read type annotations — they only run JavaScript. So the types are checked while you write, and then stripped out: the first line above leaves nothing behind but const name = "Ada";.
The check is where the value is: a name typed as string cannot be given a number, and a function that promises a string cannot quietly return nothing. The mistake is caught where it is written, not three files later when something explodes.
A useful way to read the message is to start at the call site. The checker has followed the value from the name to the argument and found that the two descriptions disagree; the line it prints is where they met, which is usually the line you need to change.
How the checker sees it
Picture the checker as a reader with a notebook. It walks the file, writes down the type of every name and every expression, and compares each use against what it wrote. When it reaches greet(name), it looks up greet, sees that the parameter is a string, checks that name is a string, then checks that the returned value matches the declared string. None of that conversation reaches the browser: after the last check the notebook is closed and the annotations are dropped.
This is why a type error feels different from a crash. A crash stops the program at the first thing that goes wrong. The checker can keep walking after a mismatch, so it may report several errors in one pass, and fixing the first often makes two disappear — they were consequences of the same wrong assumption.
What this preview runs
Every example in this course is transpiled before it runs — the annotations are erased and the page receives plain JavaScript, exactly like a browser would. The preview proves the program works; the types are what catch the mistakes it cannot show you.
So a type mistake will not stop the page here. That is not the preview being lax, that is how TypeScript itself works, and it is why a code editor running a type checker matters as much as the code does. In a real project the check runs in your editor and again in the build; here you are watching the second half of that pipeline on its own.
The check is static, the value is not
An annotation describes your code; it does not inspect your data. const age: number = 30; is checked once, when the file is compiled, and then the annotation is gone. Nothing at run time knows that age was ever meant to be a number.
That distinction explains the classic confusion. A value that arrives from a form, a URL or an API is whatever it is, no matter what type you wrote beside the variable. The annotation is a claim about the code you control; at a border, where text becomes a number, you still have to convert and check. Number("3.50") is a conversion and it runs; : number is a description and it does not.
The two errors you will meet first
The first is Type 'string' is not assignable to type 'number'. It means a value and its label disagree — either the label is wrong or the value is. Read it from the inside out and decide which one you meant.
The second is Object is possibly 'undefined'. It is not the compiler being difficult; the value really may be missing, and the fix is a check, not an exclamation mark. Learning to read those two sentences covers most of the first week.
Three habits to avoid from the start. Do not annotate everything — inference already knows what a literal is, and a redundant annotation is one more line to keep true. Do not treat an annotation as validation: it is erased, so data from outside still needs a check. And do not reach for any when a type is inconvenient; it switches off the very check you came for.
Try these next
- Change the greeting to a number and watch the preview still run; then explain why the annotation did not stop it.
- Add a second function with a
booleanparameter and abooleanreturn type. - Write the same program in plain JavaScript and compare the two files line by line.
First annotations
Annotate both values — text for the name, a number for the count — then log one line that uses them both.
3 left to do
- The name is annotated as a string
- The count is annotated as a number
- The sentence is logged
A colon after the name carries the type: const name: string = "Ada"; — the same shape works for numbers.
The annotation that disappears
Annotate the price and the quantity, then log the total to two decimal places and the run-time type of the price.
4 left to do
- The price is annotated as a number
- The quantity is annotated too
- The total is written with two decimals
- The run-time type is logged
The annotations sit after the names, and the total is a number like any other: total.toFixed(2). At run time typeof price reports the value, not the annotation.
Write the type next to the name, after a colon: const age: number = 30;. Once a value has its type, the editor can complete it, check every use, and point at the line that broke — that is the whole trade for two extra words.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What does the browser actually receive when a TypeScript file runs?
