Full Stack • Java • System Design • Cloud • AI Engineering

TypeScript Fundamentals

Master TypeScript with visual diagrams, data flow charts, and comprehensive examples covering types, interfaces, generics, and best practices

TypeScript is a strongly typed superset of JavaScript that compiles to plain JavaScript, adding optional static typing and enhanced tooling for large-scale applications.

TypeScript Compilation Architecture

flowchart TB
    A[TypeScript Source .ts] --> B[TypeScript Compiler tsc]
    B --> C[Type Checking]
    B --> D[Transpilation]
    
    C --> E{Type Errors?}
    E -->|Yes| F[Compilation Fails]
    E -->|No| G[Continue]
    
    D --> H[JavaScript Output .js]
    D --> I[Source Maps .map]
    
    H --> J[Runtime Environment]
    J --> K[Browser]
    J --> L[Node.js]
    J --> M[Deno]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style H fill:#9C27B0

Key Points:

  • Static Type Checking: Catches errors at compile time before code runs
  • Transpilation: Converts TypeScript to JavaScript for runtime execution
  • Source Maps: Enable debugging TypeScript code in browser/Node.js
  • Target Versions: Compile to ES5, ES6, or newer JavaScript versions
  • Zero Runtime Overhead: Types are removed during compilation

Type System Hierarchy

graph TB
    A[TypeScript Types] --> B[Primitive Types]
    A --> C[Object Types]
    A --> D[Special Types]
    
    B --> B1[string, number, boolean]
    B --> B2[null, undefined, symbol]
    B --> B3[bigint]
    
    C --> C1[Interface]
    C --> C2[Class]
    C --> C3[Array, Tuple]
    C --> C4[Enum]
    
    D --> D1[any - Disable checking]
    D --> D2[unknown - Type-safe any]
    D --> D3[never - No value]
    D --> D4[void - No return]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0

Key Points:

  • Primitive Types: Basic JavaScript types with TypeScript annotations
  • Object Types: Complex structures defined with interfaces or classes
  • any Type: Opts out of type checking, use sparingly
  • unknown Type: Type-safe alternative to any, requires type checking
  • never Type: Represents values that never occur (exhaustive checks)

Type Inference Flow

sequenceDiagram
    participant Dev as Developer
    participant TS as TypeScript
    participant Compiler
    
    Dev->>TS: let x = 42
    TS->>Compiler: Infer type
    Compiler->>Compiler: Analyze value
    Compiler->>TS: Type: number
    
    Dev->>TS: let arr = [1, 2, 3]
    TS->>Compiler: Infer type
    Compiler->>TS: Type: number[]
    
    Note over TS,Compiler: Automatic Type Detection

Key Points:

  • Automatic Inference: TypeScript infers types from assigned values
  • Context-Based: Infers types from function return values and parameters
  • Best of Both Worlds: Type safety without explicit annotations
  • Explicit When Needed: Add annotations for clarity or complex types

Interface vs Type Alias

graph LR
    A[Interface] --> B[Object Shapes]
    A --> C[Extension]
    A --> D[Declaration Merging]
    
    E[Type Alias] --> F[Unions]
    E --> G[Intersections]
    E --> H[Primitives]
    E --> I[Tuples]
    
    J[Use Cases] --> K[Interfaces: Objects/Classes]
    J --> L[Types: Complex Types]
    
    style A fill:#2196F3
    style E fill:#4CAF50
    style J fill:#FF9800

Key Points:

  • Interfaces: Best for defining object shapes and class contracts
  • Type Aliases: More flexible, support unions, intersections, and primitives
  • Extension: Interfaces use extends, types use intersection (&)
  • Declaration Merging: Interfaces can be reopened and extended
  • Preference: Use interfaces for objects, types for complex compositions

Class Architecture

graph TB
    A[Class Definition] --> B[Properties]
    A --> C[Methods]
    A --> D[Constructor]
    
    B --> B1[public - Accessible everywhere]
    B --> B2[private - Class only]
    B --> B3[protected - Class + Subclasses]
    B --> B4[readonly - Immutable]
    
    C --> C1[Instance Methods]
    C --> C2[Static Methods]
    C --> C3[Getters/Setters]
    
    D --> D1[Parameter Properties]
    D --> D2[Initialization]
    
    E[Inheritance] --> F[extends]
    E --> G[implements]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#F44336

Key Points:

  • Access Modifiers: Control visibility of class members (public, private, protected)
  • Constructor Shorthand: Declare and initialize properties in constructor parameters
  • Inheritance: Classes extend other classes, implement interfaces
  • Static Members: Belong to class itself, not instances

Generic Type System

flowchart TB
    A[Generic Type T] --> B[Function]
    A --> C[Interface]
    A --> D[Class]
    
    B --> B1["identity<T> value: T"]
    B --> B2[Type Reusability]
    
    C --> C1["Repository<T>"]
    C --> C2[Type-safe APIs]
    
    D --> D1["DataStore<T>"]
    D --> D2[Type-safe Collections]
    
    E[Constraints] --> F["T extends Type"]
    E --> G[Bounded Generics]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#F44336

Key Points:

  • Type Parameters: Placeholder types (T, U, K, V) for flexible, reusable code
  • Generic Functions: Work with any type while maintaining type safety
  • Generic Constraints: Restrict type parameters using extends keyword
  • Multiple Type Parameters: Use multiple generics for complex operations
  • Type Inference: TypeScript often infers generic types from usage

Union and Intersection Types

graph LR
    A[Union Types] --> B["string | number"]
    A --> C[Either/Or Logic]
    A --> D[Type Guards Needed]
    
    E[Intersection Types] --> F["Type1 & Type2"]
    E --> G[Combine Properties]
    E --> H[All Properties Required]
    
    I[Use Cases] --> J[Union: Multiple Options]
    I --> K[Intersection: Mixins]
    
    style A fill:#2196F3
    style E fill:#4CAF50
    style I fill:#FF9800

Key Points:

  • Union Types (|): Value can be one of several types
  • Intersection Types (&): Combine multiple types into one
  • Type Narrowing: Use type guards to work with union types safely
  • Discriminated Unions: Add literal type property for type discrimination

Type Guard Patterns

flowchart TB
    A[Type Guards] --> B[typeof]
    A --> C[instanceof]
    A --> D[Custom Guards]
    A --> E[in Operator]
    
    B --> B1[Primitive Types]
    B --> B2["typeof x === 'string'"]
    
    C --> C1[Class Instances]
    C --> C2["x instanceof Date"]
    
    D --> D1[User-Defined]
    D --> D2["is Type Predicate"]
    
    E --> E1[Property Check]
    E --> E2["'prop' in obj"]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#F44336

Key Points:

  • typeof: Check primitive types (string, number, boolean)
  • instanceof: Check if object is instance of class
  • Custom Type Guards: Functions with 'is' predicate for complex checks
  • in Operator: Check if property exists in object
  • Type Narrowing: Guards narrow union types to specific type

Utility Types Overview

graph TB
    A[Built-in Utility Types] --> B[Partial T]
    A --> C[Required T]
    A --> D[Readonly T]
    A --> E[Pick T K]
    A --> F[Omit T K]
    A --> G[Record K T]
    
    B --> B1[All properties optional]
    C --> C1[All properties required]
    D --> D1[All properties readonly]
    E --> E1[Select specific properties]
    F --> F1[Exclude specific properties]
    G --> G1[Create type from keys]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#F44336
    style F fill:#00BCD4
    style G fill:#FFEB3B

Key Points:

  • Partial: Makes all properties optional, useful for updates
  • Required: Makes all properties required, opposite of Partial
  • Readonly: Makes all properties immutable
  • Pick<T, K>: Creates type with subset of properties
  • Omit<T, K>: Creates type excluding specific properties
  • Record<K, T>: Creates object type with specific keys and value type

Module System Flow

sequenceDiagram
    participant A as Module A
    participant B as Module B
    participant C as Module C
    
    A->>B: export function
    A->>B: export interface
    A->>B: export class
    
    B->>C: import { items }
    B->>C: Re-export
    
    C->>C: Use imported items
    
    Note over A,B: Named Exports
    Note over B,C: Import/Re-export

Key Points:

  • Named Exports: Export multiple items from module
  • Default Exports: Single main export per module
  • Import Syntax: Destructure named exports, direct import for default
  • Re-exporting: Create barrel files to simplify imports

Decorator Pattern

flowchart LR
    A[Decorator] --> B[Class Decorator]
    A --> C[Method Decorator]
    A --> D[Property Decorator]
    A --> E[Parameter Decorator]
    
    B --> B1[Modify Class]
    C --> C1[Modify Method]
    D --> D1[Modify Property]
    E --> E1[Modify Parameter]
    
    F[Metadata] --> G[Runtime Info]
    F --> H[Reflection]
    
    style A fill:#2196F3
    style B fill:#4CAF50
    style C fill:#FF9800
    style D fill:#9C27B0
    style E fill:#F44336

Key Points:

  • Experimental Feature: Enable with experimentalDecorators in tsconfig
  • Class Decorators: Modify or replace class definition
  • Method Decorators: Add behavior to methods (logging, validation)
  • Property Decorators: Add metadata to properties
  • Common Use: Angular, NestJS frameworks use decorators extensively

Best Practices

Type Safety Guidelines

  • Enable strict mode in tsconfig.json
  • Avoid any type, use unknown instead
  • Use type guards for union types
  • Prefer interfaces for object shapes
  • Use const assertions for literal types

Code Organization

  • One interface/type per file for large types
  • Use barrel exports (index.ts) for modules
  • Group related types together
  • Document complex types with JSDoc comments

Performance Tips

  • Use type inference when obvious
  • Avoid excessive type assertions
  • Use discriminated unions for better narrowing
  • Leverage utility types instead of manual mapping