Hone logo
Hone
Problems

Dynamic Polymorphism with Type Unions and Discriminated Unions in TypeScript

TypeScript's type system offers powerful ways to model data structures. This challenge focuses on leveraging type unions and discriminated unions to achieve dynamic polymorphism, allowing you to write functions that can operate on different but related types in a type-safe manner. You will build a system that can process a variety of geometric shapes, each with its own unique properties, through a unified interface.

Problem Description

Your task is to create a set of TypeScript types and functions that represent different geometric shapes and allow for operations to be performed on them polymorphically. Specifically, you need to:

  1. Define a base type that all geometric shapes will extend or adhere to.
  2. Define distinct types for various geometric shapes (e.g., Circle, Rectangle, Triangle), each with its own specific properties.
  3. Implement a mechanism (discriminated union) that allows you to differentiate between these shapes at runtime in a type-safe way.
  4. Create a function that accepts any of these geometric shapes and performs a specific operation (e.g., calculating the area) based on its actual type.

This approach is useful for creating flexible and maintainable codebases where you need to handle a collection of related but distinct data structures uniformly.

Examples

Example 1: Processing a Circle

// Assume Shape type is defined as below (will be defined in the solution)

const myCircle: Shape = {
  kind: "circle",
  radius: 5
};

// Assume calculateArea function is defined as below (will be defined in the solution)
const area = calculateArea(myCircle);
// Expected output: 78.53981633974483 (approximately Math.PI * 5 * 5)

Example 2: Processing a Rectangle

// Assume Shape type is defined as below (will be defined in the solution)

const myRectangle: Shape = {
  kind: "rectangle",
  width: 10,
  height: 4
};

// Assume calculateArea function is defined as below (will be defined in the solution)
const area = calculateArea(myRectangle);
// Expected output: 40

Example 3: Processing a Triangle

// Assume Shape type is defined as below (will be defined in the solution)

const myTriangle: Shape = {
  kind: "triangle",
  base: 6,
  height: 8
};

// Assume calculateArea function is defined as below (will be defined in the solution)
const area = calculateArea(myTriangle);
// Expected output: 24

Constraints

  • The solution must be written entirely in TypeScript.
  • All defined types must be properly typed to ensure compile-time safety.
  • The calculateArea function must handle all defined shape types without requiring explicit type assertions or casting within its core logic (it should use the discriminated union property).
  • No external libraries are allowed for type definitions or core logic.

Notes

Consider using a literal type property (e.g., kind: "circle") to create a discriminated union. This property will serve as a tag to identify the specific shape at runtime. The calculateArea function will then use a switch statement or equivalent logic to branch based on this tag. Think about how to define the Shape type to encompass all possible geometric shapes.

Loading editor...
typescript