What happens when passing a triangle to the shape union area function?

By Google for Developers

Share:

Key Concepts

  • TypeScript Discriminated Unions: A pattern where multiple types are combined into a union, distinguished by a common literal property (the "discriminant").
  • Exhaustiveness Checking: The practice of ensuring that all possible members of a union type are handled within a conditional structure (like a switch or if-else block).
  • Runtime vs. Compile-time Behavior: The distinction between how TypeScript enforces type safety during development versus how JavaScript executes logic at runtime.

The TypeScript Challenge: Handling Union Types

The video presents a common architectural pitfall in TypeScript development: the "unhandled union member" scenario. The challenge focuses on a Shape union type and an area function designed to calculate the area based on the specific shape provided.

The Scenario

  1. The Data Structure: A union type is defined (e.g., type Shape = Circle | Square).
  2. The Logic: An area function uses a conditional structure to return the area based on the shape's properties.
  3. The "Breaking" Change: A developer adds a new member to the union (e.g., Triangle) without updating the area function to account for this new type.

The Core Question

When the area function is invoked with the newly added Triangle object, the viewer is asked to predict the outcome:

  • A) Compile error: Does TypeScript detect that the Triangle case is missing?
  • B) Returns 25: Does the function default to a specific value?
  • C) Returns undefined: Does the function fail to return a value because the Triangle case was not explicitly handled?

Technical Analysis and Implications

The Problem of "Silent" Failures

The challenge highlights a vulnerability in standard if-else or switch statements. If a developer does not implement a "default" case or an exhaustive check, TypeScript may not throw a compile-time error if the function signature allows for an implicit undefined return.

  • Exhaustiveness Checking: To prevent this, developers often use the never type in a default case. By assigning the remaining value to a variable of type never, TypeScript will throw a compile-time error if any member of the union has not been handled.
    • Example: const _exhaustiveCheck: never = shape;
    • If shape is a Triangle that hasn't been handled, the compiler will flag an error because Triangle is not assignable to never.

Logical Connections

The video illustrates the gap between Type Safety and Runtime Execution. While TypeScript is designed to catch errors during development, the configuration of the project (such as strictNullChecks) and the implementation of the logic determine whether the code remains robust when the underlying data structures evolve.


Synthesis and Takeaways

The primary takeaway is that adding new members to a union type is a "breaking change" that requires manual updates to all dependent logic. To ensure code reliability:

  1. Avoid implicit returns: Always ensure your functions handle all possible union members.
  2. Use Exhaustiveness Patterns: Implement a default case that utilizes the never type to force the TypeScript compiler to alert you if a new union member is added but not handled.
  3. Proactive Refactoring: When modifying shared types, developers must treat the resulting compiler errors as a guide to updating the entire codebase, rather than ignoring them or relying on runtime defaults.

Chat with this Video

AI-Powered

Load the transcript when you're ready to chat so the initial page stays lighter.

Related Videos

Ready to summarize another video?

Summarize YouTube Video