Lesson 3 • Beginner
Interfaces and Type Aliases 📐
Define the shape of objects, create reusable custom types, and master union/intersection types — the foundation of scalable TypeScript code.
What You'll Learn in This Lesson
- • Interfaces with optional, readonly, and extended properties
- • Type aliases for unions, intersections, and primitives
- • When to use
interfacevstype - • Index signatures and function type interfaces
- • Discriminated unions for type-safe state management
1️⃣ Interfaces
Interfaces define the structure (shape) of objects. They specify which properties must exist, their types, and whether they're optional or readonly. Interfaces can extend other interfaces for composition.
Try It: Interfaces
Optional, readonly, extended, and composed interfaces
// Interfaces — Define Object Shapes
console.log("=== Basic Interface ===");
console.log();
console.log("interface User {");
console.log(" id: number;");
console.log(" name: string;");
console.log(" email: string;");
console.log(" isActive: boolean;");
console.log("}");
console.log();
let user = { id: 1, name: "Alice", email: "alice@example.com", isActive: true };
console.log("const user: User = " + JSON.stringify(user, null, 2));
console.log();
// Optional properties
console.log("=== Opti
...2️⃣ Type Aliases
Type aliases create named types for any shape — including unions (A | B), intersections (A & B), primitives, tuples, and function types. They're more flexible than interfaces.
Try It: Type Aliases
Unions, intersections, literal types, and interface vs type comparison
// Type Aliases — Flexible Custom Types
console.log("=== Type Aliases ===");
console.log();
console.log("type Point = { x: number; y: number; };");
console.log("type ID = string | number;");
console.log("type Callback = (data: string) => void;");
console.log();
// Union types
console.log("=== Union Types (|) ===");
console.log("type Status = 'active' | 'inactive' | 'pending';");
console.log();
let statuses = ["active", "inactive", "pending"];
for (let s of statuses) {
console.log(" status =
...3️⃣ Advanced Patterns
Discriminated unions (tagged unions) are one of TypeScript's most powerful patterns. By adding a kind property, TypeScript can narrow types in switch statements — enabling safe, exhaustive handling of all cases.
Try It: Advanced Patterns
Index signatures, function interfaces, and discriminated unions
// Advanced Interface Patterns
console.log("=== Index Signatures ===");
console.log("interface StringMap {");
console.log(" [key: string]: string; // any string key → string value");
console.log("}");
let env = { NODE_ENV: "production", API_KEY: "abc123", PORT: "3000" };
console.log("const env: StringMap = " + JSON.stringify(env));
console.log();
console.log("=== Function Interfaces ===");
console.log("interface Formatter {");
console.log(" (input: string): string;");
console.log("}");
conso
...⚠️ Common Mistakes
{ loading: boolean; error: string | null; data: T | null } allows impossible states. Use discriminated unions instead.interface for public APIs (they can be augmented). Use type for internal utility types.📋 Quick Reference
| Pattern | Syntax |
|---|---|
| Interface | interface User { name: string } |
| Optional | bio?: string |
| Readonly | readonly id: number |
| Union | type ID = string | number |
| Intersection | type A = B & C |
| Literal | type Dir = 'up' | 'down' |
🎉 Lesson Complete!
You can define any object shape! Next, learn to type functions and write flexible generic code.
Sign up for free to track which lessons you've completed and get learning reminders.