Chapter 11: TypeScript Union Types

TypeScript – Union Types. If TypeScript is a superhero, union types are its superpower. They’re what make TypeScript expressive, flexible, and incredibly safe all at once.

Let me start with a simple analogy:

Imagine you’re at a coffee shop. You order a drink. What can you get? Coffee, tea, hot chocolate, or a smoothie. You can’t get a hamburger or a pizza. The menu defines the union of possible drinks.

Union types do the same thing in TypeScript – they define a type that can be ONE of several possible types, but nothing else.

Part 1: What Is a Union Type?

union type is a type formed from two or more other types, representing values that can be ANY of those types. We use the vertical bar | to separate each type.

typescript

Think of it as “THIS or THAT or THE OTHER” – like a multiple-choice question where only certain answers are correct.

Part 2: Basic Union Types

Primitives Unions

typescript

Type Aliases with Unions

typescript

Part 3: Working with Union Types – The TypeScript Challenge

Here’s the thing about union types – TypeScript is very protective. When you have a value that could be multiple types, TypeScript won’t let you assume it’s just one of them:

typescript

This is not a limitation – it’s a safety feature! TypeScript is saying: “I don’t know which type this is right now, so I won’t let you do anything that might crash.”

Solution 1: Type Narrowing with typeof

typescript

Solution 2: Type Narrowing with instanceof

typescript

Solution 3: Type Predicates (Custom Type Guards)

typescript

Part 4: Union Types with Arrays

Unions become really powerful when combined with arrays:

typescript

Real-World Example: API Response Handling

typescript

Part 5: Discriminated Unions (Tagged Unions)

This is where union types become absolutely beautiful. A discriminated union uses a common property (the discriminator) to distinguish between different types in the union:

typescript

Why this is amazing:

  • TypeScript knows EXACTLY which properties exist in each case

  • If you miss a case, TypeScript will warn you

  • Adding new shapes is safe – TypeScript shows you everywhere that needs updating

Exhaustive Checking with never

typescript

Part 6: Advanced Union Patterns

Nullable Types

typescript

Union of Functions

typescript

Recursive Unions

typescript

Union of Template Literals

typescript

Part 7: Real-World Case Study – E-Commerce System

Let’s build a comprehensive order processing system that demonstrates the power of union types:

typescript

Part 8: Union Types vs Other TypeScript Features

Unions vs Enums

typescript

Unions vs Inheritance

typescript

Unions vs Optional Properties

typescript

Part 9: Common Pitfalls and Solutions

Pitfall 1: Overly Broad Unions

typescript

Pitfall 2: Not Narrowing Enough

typescript

Pitfall 3: Forgetting About Null/Undefined

typescript

Pitfall 4: Complex Nested Unions

typescript

Part 10: Best Practices Summary

DO:

  1. Use discriminated unions for complex state management

  2. Narrow types explicitly before operations

  3. Use exhaustive checking with never

  4. Name your unions with type aliases

  5. Start specific, expand as needed

DON’T:

  1. Don’t use overly broad unions (avoid string | number when you mean specific values)

  2. Don’t forget to handle all cases in discriminated unions

  3. Don’t use unions when inheritance makes more sense

  4. Don’t nest unions too deeply – break them down

The Big Picture

Union types are TypeScript’s way of saying “I want to be flexible about what I accept, but I still want to be safe about how I use it.”

They transform the way you think about types:

  • From “This must be exactly X” → “This can be X, Y, or Z”

  • From “I’ll check at runtime” → “The compiler ensures I check before using”

  • From “Magic strings everywhere” → “These are the only valid values”

Every time you write a union type, you’re creating a contract. You’re saying to other developers: “Your value can be one of these specific things, but nothing else. And I promise to check which one it is before I do anything with it.”

This is the essence of TypeScript – making the impossible states impossible, and making the possible states explicit and safe.

Remember: Union types aren’t about being less strict. They’re about being precisely flexible. They define exact sets of allowed values, not vague categories. When you say type Status = "pending" | "approved" | "rejected", you’re not being less strict than string – you’re being MORE strict, because you’re saying “not just any string, only these three specific strings.”

This precision is what makes TypeScript so powerful. It catches bugs before they happen, documents your code automatically, and makes refactoring fearless.

Does this help clarify union types? Would you like me to elaborate on any specific aspect or show more real-world examples of union patterns?

This response is AI-generated, for reference only.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *