Six lessons to take you from complete beginner to confidently writing typed JavaScript. No prior TypeScript experience needed.
JavaScript with a superpower — catch errors before they reach production.
TypeScript is a programming language created by Microsoft in 2012. It's essentially JavaScript with types added on top.
Types help catch errors before running the program, making code more reliable.
let age: number = 25; age = 30; // ✅ OK // age = "hello" ❌ Error // Type 'string' not assignable
Find bugs while coding, not in production. The compiler is your first line of defense.
Your editor knows exactly what properties and methods are available at all times.
Types explain what data functions expect and return — readable code by design.
Rename variables, change types — the compiler tells you everywhere that needs updating.
Download from nodejs.org
npm install -g typescript tsc --version
Best TypeScript support. Download from code.visualstudio.com
function greet(name: string): string { return `Hello, ${name}!`; } console.log(greet("World")); // Hello, World!
TypeScript compiles to plain JavaScript. Run tsc hello.ts to compile, then node hello.js to run.
The fundamental building blocks — the seven basic types in TypeScript.
In TypeScript, primitives are the most basic types: string, number, boolean, bigint, symbol, null, and undefined.
let name: string = "Ruth"; let msg = `Hi ${name}!`;
let age: number = 20; let price: number = 9.99;
let active: boolean = true; let done: boolean = false;
let big: bigint = 12345678901234n;
let id: symbol = Symbol("id"); // Always unique
let empty: null = null; let notSet: undefined = undefined;
// any — disables type checking (avoid when possible) let anything: any = 42; anything = "now a string"; // no error // unknown — safer than any, must narrow before use let value: unknown = getData(); if (typeof value === "string") { console.log(value.toUpperCase()); // ✅ safe now } // never — for things that should never happen function crash(): never { throw new Error("This always throws"); }
Typed collections — enforce what goes in, and where.
Method 1: Type[]
let nums: number[] = [1, 2, 3]; let names: string[] = ["Alice", "Bob"];
Method 2: Array<Type>
let nums: Array<number> = [1, 2, 3]; let names: Array<string> = ["Alice", "Bob"];
Tuples are arrays with a fixed length and a specific type at each position. Perfect for structured data.
let person: [string, number] = ["Alice", 25]; // person[0] → string, person[1] → number let color: [number, number, number] = [255, 0, 128]; // RGB value — always 3 numbers // Tuple with label (TS 4.0+) let coords: [x: number, y: number] = [10, 20];
let fruits: string[] = ["apple", "banana", "orange"]; fruits.push("grape"); // add to end fruits.pop(); // remove from end fruits.length; // 3 let upper = fruits.map(f => f.toUpperCase()); // ["APPLE", "BANANA", "ORANGE"] let long = fruits.filter(f => f.length > 5); // ["banana", "orange"] let found = fruits.find(f => f.startsWith("a")); // "apple"
Define the shape of your data — reusable, readable, robust.
// Inline object type let user: { name: string; age: number } = { name: "Alice", age: 25 }; // Optional property with ? let product: { name: string; discount?: number } = { name: "Laptop" // discount is optional — no error };
interface User { name: string; age: number; email: string; isActive?: boolean; // optional readonly id: number; // can't be changed after init } let user1: User = { name: "Alice", age: 25, email: "[email protected]", id: 1 }; // user1.id = 99; ❌ readonly — cannot reassign
interface Animal { name: string; speak(): string; } // Extend an existing interface interface Dog extends Animal { breed: string; fetch(): void; } const rex: Dog = { name: "Rex", breed: "Labrador", speak: () => "Woof!", fetch: () => console.log("Fetching...") };
Type your parameters and return values — no surprises at runtime.
// Basic typed function function add(a: number, b: number): number { return a + b; } // Optional parameter with ? function greet(name: string, greeting?: string): string { return `${greeting ?? "Hello"}, ${name}!`; } // Default parameter function power(base: number, exp: number = 2): number { return base ** exp; } power(3); // 9 (uses default exp=2) power(3, 3); // 27
// Arrow function const multiply = (a: number, b: number): number => a * b; // void — function returns nothing const logMessage = (msg: string): void => { console.log(msg); }; // Rest parameters — collect extra args into an array function sum(...nums: number[]): number { return nums.reduce((acc, n) => acc + n, 0); } sum(1, 2, 3, 4, 5); // 15
// Typing a function as a variable let calculator: (a: number, b: number) => number; calculator = (x, y) => x + y; // ✅ calculator = (x, y) => x * y; // ✅ // Callback function type function process( items: string[], callback: (item: string) => void ): void { items.forEach(callback); } process(["a", "b", "c"], item => console.log(item));
Flexible types that handle multiple possibilities — and reusable names for complex shapes.
// Union type — value can be one of several types let id: string | number; id = "ABC123"; // ✅ id = 12345; // ✅ function printId(id: string | number): void { // Narrow to handle each type: if (typeof id === "string") { console.log(id.toUpperCase()); } else { console.log(id.toFixed(2)); } }
// Give a union type a reusable name type ID = string | number; // Type alias for an object shape type User = { name: string; age: number; }; let user: User = { name: "Alice", age: 25 }; // interface vs type — both work for objects! // Use interface when you expect extension (extends) // Use type for unions, intersections, and complex types
// Restrict to exact string values type Status = "pending" | "approved" | "rejected"; type Role = "admin" | "user" | "guest"; type Dir = "north" | "south" | "east" | "west"; let status: Status = "pending"; // ✅ // status = "shipped"; ❌ Error — not in union // Even numbers can be literals! type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
Type vs Interface: Both work for object shapes. Use interface when you plan to extend it with extends. Use type for unions, intersections, and primitive aliases.