TypeScript — JavaScript with a Safety Net
What you'll learn
- What "types" mean and why companies demand TypeScript
- Reading TypeScript signatures (you'll see them everywhere)
- Union types — the pattern behind "one of these exact values"
- Practice the thinking with runnable exercises
- The exact setup steps for your machine
TypeScript needs a compile step, so the runnable parts use JavaScript to practice type-thinking — then you'll set up the real thing locally.
Labeled boxes 🏷️
In the JavaScript lesson, variables were boxes. JavaScript lets you put anything in any box, any time:
let age = 25;
age = "twenty five"; // JS says: sure, why not! 🤷
age * 2; // NaN … your app just broke, silently
That flexibility is exactly what causes most bugs in big projects.
TypeScript = JavaScript + labels on the boxes. You declare what a box may hold, and a checker yells at you while you type — not after your users find the bug:
let age: number = 25;
age = "twenty five";
// ❌ Error: Type 'string' is not assignable to type 'number'
Functions get labels too — this is the part you'll read every day in every modern codebase:
function add(a: number, b: number): number {
return a + b;
}
add(2, 3); // ✅ 5
add(2, "3"); // ❌ caught before you even run it
Read it as: "add takes two numbers and gives back a number." And you can define the shape of whole objects:
interface User {
name: string;
age: number;
email?: string; // ? = optional
}
The payoff: your editor autocompletes everything, refactors safely, and the compiler catches a whole category of bugs before they ship. That's why most job listings ask for it — TypeScript is not a new language to learn, it's the same JavaScript with the safety net on.
Be the type checker! Until your local TS is set up, play the compiler's role by hand.
Write a function safeAdd(a, b) that:
- Returns the sum if both arguments are numbers
- Returns the text
"TypeError"if either one is not a number
(Check with typeof x === "number" — that's literally what the word TypeScript is about.)
Union types — "one of these, exactly" 🎯
Sometimes string is too loose. A task's status isn't any string — it's only ever "loading", "success", or "error". TypeScript lets you say that precisely with a union type:
type Status = "loading" | "success" | "error";
function showStatus(status: Status) {
console.log("Current status:", status);
}
showStatus("success"); // ✅
showStatus("done"); // ❌ Error: "done" is not assignable to type 'Status'
The | (pipe) means "or" — Status can be exactly one of those three strings, nothing else. Typo "scucess" and the compiler catches it instantly, before you ever run the code. This is far stronger than a plain string, which would happily accept any typo.
You'll also see type used to name any shape, not just unions:
type Point = { x: number; y: number };
(interface and type overlap a lot in everyday use — interface is more common for object shapes, type is more common for unions like Status above.)
Simulate a union-type checker. Write isValidStatus(status) that returns true only if status is exactly "loading", "success", or "error" — this is exactly what the TypeScript compiler checks for you automatically with a union type.
Real-world case study: this platform's own types 🔍
Union types aren't academic — this exact lesson platform uses them constantly. Its language system is typed as type Lang = "en" | "ar" — so passing anything other than exactly those two strings is a compile error, guaranteeing the app can never end up in a broken third "language." The code runner you're using right now types its languages as type RunnerLang = "web" | "js" | "python". Same idea as your Status exercise, just wired into a real production app.
Lab exercise 1
TypeScriptGraded in Code LabLet the types do the checking. Define the types, then the function. Each input line is name:score (score is an integer 0-100, names contain no colon).
Implement summarize(entries: Entry[]): Summary where Summary has best (the entry with the highest score; on a tie the one that appears first), average (mean score) and passed (how many entries have a score of 60 or more). Print three lines:
best: <name> (<score>)
average: <mean with 1 decimal>
passed: <n>/<total>
For empty input print no entries.
- Best, average and pass count
- The first entry wins a tie
- A single entry at the pass mark
- Empty input
Example run
- Input
amal:90 bilal:55 chen:72
- Expected output
best: amal (90) average: 72.3 passed: 2/3
import * as fs from "node:fs";
// TODO 1: describe a line of input
interface Entry {
name: string;
}
// TODO 2: describe the result (best entry, average, passed count)
interface Summary {
best: Entry;
}
More lines in Code Lab: 20
Hints and instant feedback are in Code Lab. Optional practice: it does not block finishing the lesson.
JavaScript and Python also run in your browser without an account; other languages use the secure server runner and need a free account.
Question 1 of 6
What does TypeScript add to JavaScript?
Question 2 of 6
What does this mean: function greet(name: string): string ?
Question 3 of 6
In interface User { email?: string } — what does the ? mean?
Question 4 of 6
When are TypeScript errors caught?
Question 5 of 6
What does type Status = "loading" | "success" | "error" mean?
Question 6 of 6
Why is a union type stricter than a plain string?
Set up the real thing (15 minutes)
- In any project:
npm install -D typescriptthennpx tsc --init - Rename a
.jsfile to.ts— errors appear as red squiggles in VS Code - Label your functions' parameters and returns; define one
interfaceand one uniontype - The official handbook (Resources tab) chapter "TypeScript for JavaScript Programmers" takes 20 minutes and covers 80% of daily usage
Reality check: on the job you'll mostly read types others wrote and add types to your own functions. You now know how to do both.
Practice
Reading is not learning until you run something. Pick one.
Graded lab exercises
- Lab exercise 1TypeScriptNot passed yet Try in Code Lab