Courses / JavaScript / TypeScript Introduction
    Back to Course

    💡 Running TypeScript

    TypeScript requires compilation to JavaScript. To practice:

    • Use the TypeScript Playground for instant browser testing
    • Install TypeScript: npm install -g typescript
    • Compile with: tsc filename.ts

    Intro to TypeScript & Strong Typing Concepts

    Master TypeScript's type system to catch bugs at compile-time, enable better tooling, and write more maintainable code. Learn types, interfaces, generics, and utility types.

    What You'll Learn

    • Type annotations
    • Interfaces & type aliases
    • Generics
    • Type narrowing & guards
    • Utility types (Partial, Pick, Omit)
    • Mapped & conditional types

    Why TypeScript?

    JavaScript is dynamically typed — variables can hold any value, functions accept anything, and errors only appear at runtime. TypeScript adds a compile-time type system that catches bugs before your code runs.

    JavaScript Problems

    • • Runtime errors in production
    • • No autocomplete for object shapes
    • • Wrong argument types accepted
    • • Undefined property access
    • • Risky refactoring

    TypeScript Solutions

    • ✓ Compile-time error detection
    • ✓ Full IDE autocomplete
    • ✓ Type-safe function calls
    • ✓ Guaranteed property access
    • ✓ Safe, confident refactoring

    Basic Type Annotations

    Type annotations tell TypeScript exactly what kind of value a variable, parameter, or return value should hold.

    Basic Type Annotations

    TypeScript primitive types, arrays, objects, and functions

    Try it Yourself »
    JavaScript
    // TypeScript Basic Type Annotations
    
    // Primitive types
    let name: string = "Boopie";
    let age: number = 16;
    let alive: boolean = true;
    
    // Arrays
    let scores: number[] = [10, 20, 30];
    let names: string[] = ["Alice", "Bob"];
    let mixed: (string | number)[] = [1, "two", 3];
    
    // Objects
    let user: { name: string; age: number } = {
      name: "Boopie",
      age: 16
    };
    
    // Functions with types
    function add(a: number, b: number): number {
      return a + b;
    }
    
    // Arrow functions with types
    const multiply = (x: nu
    ...

    Interfaces

    Interfaces describe the shape of objects. They define what properties an object must have and their types, making your code predictable and self-documenting.

    Interfaces

    Define object shapes with optional and readonly properties

    Try it Yourself »
    JavaScript
    // Interfaces - Describe Object Shapes
    
    interface User {
      name: string;
      age: number;
      email: string;
      active: boolean;
    }
    
    // Using the interface
    const user: User = {
      name: "Boopie",
      age: 16,
      email: "boopie@example.com",
      active: true
    };
    
    // Optional properties
    interface Product {
      id: number;
      name: string;
      description?: string; // optional
      price: number;
    }
    
    const product: Product = {
      id: 1,
      name: "Widget",
      price: 29.99
      // description is optional, so we can omit it
    };
    
    
    ...

    Type Aliases & Union Types

    Type aliases create reusable type definitions. Union types allow a value to be one of several types, while literal types restrict values to specific options.

    Type Aliases & Union Types

    Create reusable types and union/intersection types

    Try it Yourself »
    JavaScript
    // Type Aliases & Union Types
    
    // Type alias for primitives
    type ID = string | number;
    
    let userId: ID = 123;
    userId = "abc-123"; // Both are valid
    
    // Type alias for objects
    type Point = {
      x: number;
      y: number;
    };
    
    const origin: Point = { x: 0, y: 0 };
    
    // Union types - multiple possible types
    type Status = "pending" | "approved" | "rejected";
    
    let orderStatus: Status = "pending";
    orderStatus = "approved";   // ✓ OK
    // orderStatus = "unknown"; // ❌ Error!
    
    // Literal types
    type Size = "sm" 
    ...

    Generics

    Generics create reusable, type-safe components that work with any type. They're essential for building libraries, APIs, and flexible utilities.

    Generics

    Create reusable, type-safe components that work with any type

    Try it Yourself »
    JavaScript
    // Generics - Reusable Type-Safe Code
    
    // Generic function
    function identity<T>(value: T): T {
      return value;
    }
    
    // Usage - type is inferred or explicit
    const num = identity(42);           // T is number
    const str = identity<string>("hi"); // T is string
    
    // Generic with arrays
    function firstElement<T>(arr: T[]): T | undefined {
      return arr[0];
    }
    
    const first = firstElement([1, 2, 3]);      // number | undefined
    const firstStr = firstElement(["a", "b"]);  // string | undefined
    
    // Generic inte
    ...

    💡 Key Insight: Generics are type placeholders. When you call a generic function, TypeScript infers or you specify the actual type, giving you full type safety without duplicating code.

    Type Narrowing & Guards

    Type narrowing lets TypeScript understand the specific type within conditional blocks. Discriminated unions are the most powerful pattern for complex data.

    Type Narrowing & Guards

    Use typeof, instanceof, and discriminated unions

    Try it Yourself »
    JavaScript
    // Type Narrowing & Type Guards
    
    // typeof narrowing
    function printValue(value: string | number) {
      if (typeof value === "string") {
        // TS knows value is string here
        console.log(value.toUpperCase());
      } else {
        // TS knows value is number here
        console.log(value.toFixed(2));
      }
    }
    
    // instanceof narrowing
    class Dog {
      bark() { console.log("Woof!"); }
    }
    
    class Cat {
      meow() { console.log("Meow!"); }
    }
    
    function makeSound(animal: Dog | Cat) {
      if (animal instanceof Dog) {
        an
    ...

    Utility Types

    TypeScript includes powerful built-in utility types that transform existing types. These are essential for everyday TypeScript development.

    Utility Types

    Built-in type transformers like Partial, Pick, Omit, and Record

    Try it Yourself »
    JavaScript
    // Utility Types - Built-in Type Transformers
    
    interface User {
      id: number;
      name: string;
      email: string;
      password: string;
      createdAt: Date;
    }
    
    // Partial<T> - Make all properties optional
    type PartialUser = Partial<User>;
    // { id?: number; name?: string; email?: string; ... }
    
    function updateUser(id: number, updates: Partial<User>) {
      // Can pass any subset of User properties
    }
    
    updateUser(1, { name: "New Name" }); // ✓ OK
    
    // Required<T> - Make all properties required
    interface Confi
    ...

    Mapped & Conditional Types

    Advanced type transformations let you create new types programmatically. These power the utility types and enable sophisticated type logic.

    Mapped & Conditional Types

    Advanced type transformations and conditional logic

    Try it Yourself »
    JavaScript
    // Mapped Types & Conditional Types
    
    // Basic mapped type
    type Readonly<T> = {
      readonly [K in keyof T]: T[K];
    };
    
    type Optional<T> = {
      [K in keyof T]?: T[K];
    };
    
    // Real example
    interface User {
      id: number;
      name: string;
      email: string;
    }
    
    type ReadonlyUser = Readonly<User>;
    // All properties are now readonly
    
    // Mapped type with transformation
    type Getters<T> = {
      [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
    };
    
    type UserGetters = Getters<User>;
    // { getId: () => numb
    ...

    Async Types & Promises

    TypeScript fully understands asynchronous code. Type your async functions, API responses, and error handling for complete safety.

    Async Types & Promises

    Type async functions, API responses, and error handling

    Try it Yourself »
    JavaScript
    // Async Types & Promise Handling
    
    // Typing async functions
    async function fetchUser(id: number): Promise<User> {
      const response = await fetch(`/api/users/${id}`);
      return response.json();
    }
    
    // Using the Awaited utility type
    type ResolvedUser = Awaited<ReturnType<typeof fetchUser>>;
    // User
    
    // Promise with union types
    type ApiResult<T> =
      | { success: true; data: T }
      | { success: false; error: string };
    
    async function fetchData(): Promise<ApiResult<User[]>> {
      try {
        const response
    ...

    Decorators

    Decorators are a meta-programming feature for modifying classes, methods, and properties. They're used extensively in Angular, NestJS, and TypeORM.

    Decorators

    Meta-programming for classes, methods, and properties

    Try it Yourself »
    JavaScript
    // Decorators - Metaprogramming for Classes
    // Enable in tsconfig.json: "experimentalDecorators": true
    
    // Class decorator
    function Logger(constructor: Function) {
      console.log("Class created:", constructor.name);
    }
    
    @Logger
    class User {
      constructor(public name: string) {}
    }
    // Logs: "Class created: User"
    
    // Decorator factory - returns a decorator
    function Component(config: { selector: string }) {
      return function(constructor: Function) {
        console.log("Component:", config.selector);
      };
    ...

    Declaration Files

    Declaration files (.d.ts) add type information to JavaScript libraries. Module augmentation lets you extend existing types.

    Declaration Files

    Add type information to JavaScript libraries

    Try it Yourself »
    JavaScript
    // Declaration Files (.d.ts) - Adding Types to JS Libraries
    
    // Creating a declaration file for a JavaScript library
    // utils.d.ts
    declare module "my-utils" {
      export function sum(a: number, b: number): number;
      export function capitalize(str: string): string;
      export const VERSION: string;
    }
    
    // Now you can import with full type support
    // import { sum, capitalize, VERSION } from "my-utils";
    
    // Ambient declarations for global variables
    declare const API_URL: string;
    declare const DEBUG: boo
    ...

    Key Takeaways

    Core Concepts

    • ✓ Type annotations for safety
    • ✓ Interfaces for object shapes
    • ✓ Generics for reusable code
    • ✓ Union & literal types
    • ✓ Type narrowing & guards

    Advanced Features

    • ✓ Utility types (Partial, Pick, Omit)
    • ✓ Mapped & conditional types
    • ✓ Decorators for meta-programming
    • ✓ Declaration files for JS libs
    • ✓ Module augmentation

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous