﻿Topic 3: Advanced Types (Union, Intersection, Mapped, Conditional, Utility Types)

## 1. Problem Statement

## ViBe’s Dynamic Dashboard Dilemma

ViBe’s dashboard must show:

-   Each learner’s progress (quizzes, videos, assignments, etc.)
    
-   Each instructor’s engagement (courses taught, feedback given)
    
-   Each admin’s reports (user stats, revenue, system alerts)
    

But the data is always changing:

-   Some learners do only quizzes, others only videos.
    
-   Some instructors are also learners.
    
-   Admins want to combine, filter, and transform data for custom reports.
    
<img src="https://i.postimg.cc/mr8yGgjc/vibe-fin.png" width="400px" />

**The problem:**  
How do you build a system that can:

-   Combine different data shapes safely?
    
-   Handle users with multiple roles?
    
-   Transform or filter data for any report, without rewriting code for every new dashboard feature?
    

**Expected outcome:**

-   Flexible, type-safe code that adapts to real-world data complexity.
    
-   Reports and features that are easy to extend, without bugs or duplication.
    

## 2. Learning Objectives

By the end of this lesson, you’ll be able to:

-   Use union and intersection types to model flexible data.
    
-   Use mapped types to transform or generate new data shapes.
    
-   Use conditional types to make types adapt to situations.
    
-   Use utility types to quickly adjust existing types.
    
-   Build robust, future-proof code for ViBe’s dynamic needs.
    

## 3. Concept Introduction with Analogy

## The Swiss Army Knife Analogy

Imagine your code is a Swiss Army knife:

-   Sometimes you need just a knife (one type).
    
-   Sometimes you need a knife and a screwdriver at once (combine types).
    
-   Sometimes you want to quickly reshape a tool for a special job (transform types).
    
-   Sometimes you want a tool that adapts itself based on the job (conditional types).
    

**Advanced types**  let you build tools that are just as flexible and adaptable as your real-world needs.

## **Union Types**
A union  type allows a  value to be  **one of several  types**.  
It’s written  with the  `|`  (“or”) operator.

## **How They  Work**

-   When  a value is a  union, TypeScript only  allows you to  use members/methods that  are common to  all types in  the union.
    
-   To  use type-specific properties, you must  **narrow**  the type  (using  `typeof`,  `in`, or  discriminant properties).

  ```typescript
type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // OK
value = 42;      // OK
value = true;    // Error
  ```
## **Intersection Types**

An intersection type combines  **multiple types into one**  using the  `&`  (“and”) operator.

## **How They Work**

-   The resulting type has  **all properties**  of the intersected types.
    
-   If there’s a property with the same name but different types, TypeScript will error.

  ```typescript
type A = { a: number };
type B = { b: string };
type AB = A & B; // { a: number; b: string }

const obj: AB = { a: 1, b: "hi" }; // OK

  ```
## **Mapped Types**

Mapped types let you  **transform each property**  in a type, often used with  `keyof`  and unions.

## **How They Work**

-   You “map over” the keys of a type or union and create a new type for each key.
    
-   Used for making all properties optional, readonly, or changing their types.

  ```typescript
type User = { id: string; name: string; };
type OptionalUser = { [K in keyof User]?: User[K] }; // All properties optional
  ```

## **Conditional Types**

## **What Are They?**

Conditional types let you  **choose a type based on a condition**  at the type level, using the form  `T extends U ? X : Y`.

-   TypeScript checks if the type on the left of  `extends`  is assignable to the one on the right.

-   If true, the first branch is used; otherwise, the second.

```typescript
type IsString<T> = T extends string ? true : false;

type A = IsString<string>; // true
type B = IsString<number>; // false
  ```

## 4. Step-by-Step Data Modeling

Let’s model ViBe’s users and reports:

  ```typescript
// Basic user types
type Learner = { id: string; quizzesCompleted: number };
type Instructor = { id: string; coursesTaught: number };
type Admin = { id: string; accessLevel: "basic" | "super" };

// Some users have more than one role!
type MultiRoleUser = Learner & Instructor; // Intersection: both!
type AnyUser = Learner | Instructor | Admin; // Union: one or the other
  ```

## 5. Live Code Walkthrough (Step-by-Step, Explained)

## **A. Union Types: One or the Other**
 ```typescript
function printUserInfo(user: AnyUser) {
  if ("quizzesCompleted" in user) {
    console.log(`Learner: ${user.quizzesCompleted} quizzes completed`);
  } else if ("coursesTaught" in user) {
    console.log(`Instructor: ${user.coursesTaught} courses taught`);
  } else {
    console.log(`Admin: Access - ${user.accessLevel}`);
  }
}
 ```

-   **Union types**  let you accept different shapes and handle each safely.
## **B. Intersection Types: Both at Once**
 ```typescript
const alice: MultiRoleUser = {
  id: "alice123",
  quizzesCompleted: 10,
  coursesTaught: 2
};

 ```
-   **Intersection types**  let you combine all properties for users with multiple roles.

## **C. Mapped Types: Transform Data Shapes**

Suppose you want to track module progress for each learner:

 ```typescript
type ModuleStatus = "not-started" | "in-progress" | "completed";

// For any list of module IDs, generate a progress map:
type ProgressMap<Modules extends string> = {
  [K in Modules]: ModuleStatus;
};

type MyModules = "quiz1" | "video2" | "assignment3";
type MyProgress = ProgressMap<MyModules>;

// Result: { quiz1: ModuleStatus; video2: ModuleStatus; assignment3: ModuleStatus }
 ```

## **D. Conditional Types: Adapting to Data**

Suppose you want to allow feedback only if a module is completed:

 ```typescript
type FeedbackAllowed<T extends ModuleStatus> = T extends "completed" ? string : never;

type FeedbackForQuiz = FeedbackAllowed<"completed">; // string
type FeedbackForVideo = FeedbackAllowed<"in-progress">; // never
 ```
## **E. Utility Types: Quick Type Transformations**

Suppose you want a type where all fields are optional for a draft report:

 ```typescript
type LearnerReport = {
  name: string;
  score: number;
  feedback: string;
};
type DraftReport = Partial<LearnerReport>; // All fields now optional
 ```
Or make a type where all fields are read-only:

 ```typescript
type ReadonlyReport = Readonly<LearnerReport>;
 ```

## 6. Challenge 

**Your Turn!**

1.  Create a  `type`  called  `InstructorOrAdmin`  that can be either an  `Instructor`  or an  `Admin`.
    
2.  Given a type  `Assignment = { title: string; dueDate: Date; points: number; }`, create a type  `ReadonlyAssignment`  where none of the fields can be changed.
    
3.  Given a type  `LearnerStats = { quizzes: number; videos: number; assignments: number; }`, create a type  `StatsAsStrings`  that has the same keys, but all values are strings.

## 7. Quick Recap & Key Takeaways


-   **Unions:**  When a value can be one of several types (e.g., API responses, user roles).
    
-   **Intersections:**  When you need a type that combines multiple behaviors or data sources.
    
-   **Mapped Types:**  When you want to transform or generate types based on existing ones (e.g., make all fields optional).
    
-   **Conditional Types:**  For type-level logic and type transformations (e.g., extracting types, enforcing rules).
    
-   **Utility Types:**  For common type manipulations and code reuse.
    

## 8. (Optional) Programmer’s Workflow Checklist

-   Use  **union**  when a value can be one of many types.
    
-   Use  **intersection**  when you need all properties from multiple types.
    
-   Use  **mapped**  and  **utility types**  to quickly reshape data.
    
-   Use  **conditional types**  for smart, rules-based types.
    
-   Test your types with real data and scenarios.
    

## 9. Coming up Next

***Congratulations!***  
You’ve mastered the Swiss Army knife of TypeScript types.  
Next, imagine combining all these tools to build a reporting engine that adapts to any new content or user type ViBe invents in the future!
