Hone logo
Hone
Problems

Type-Safe Builder Pattern in TypeScript

The Builder pattern is a creational design pattern that allows you to construct complex objects step-by-step. In TypeScript, achieving type safety within a builder is crucial to prevent errors and ensure the final object conforms to a defined structure. This challenge asks you to implement a type-safe builder for a Product object, ensuring that all required properties are set before the object is finalized.

Problem Description

You need to create a ProductBuilder class in TypeScript that allows constructing Product objects in a controlled and type-safe manner. The Product object has the following properties:

  • name: string (required)
  • price: number (required, must be positive)
  • description: string (optional)
  • category: string (optional)
  • tags: string[] (optional)

The ProductBuilder should provide methods for setting each property of the Product object. It should also include a build() method that returns a fully constructed Product object. The build() method should throw an error if any required properties (name, price) are not set.

Key Requirements:

  • Type Safety: The builder should enforce type safety for all properties.
  • Required Properties: The build() method must ensure that all required properties are set.
  • Positive Price: The price property must be a positive number.
  • Immutability (Optional but Recommended): While not strictly required, consider making the builder methods return the builder instance itself to allow for method chaining.

Expected Behavior:

  • Calling builder methods should update the internal state of the builder.
  • Calling build() with all required properties set should return a Product object with the specified properties.
  • Calling build() with missing required properties should throw an error with a descriptive message.
  • Setting a non-positive price should throw an error.

Edge Cases to Consider:

  • What happens if tags is not an array of strings?
  • What happens if price is negative or zero?
  • How to handle optional properties gracefully?

Examples

Example 1:

Input:
builder.setName("Awesome Widget").setPrice(29.99).setDescription("A truly awesome widget").build()

Output:
{ name: "Awesome Widget", price: 29.99, description: "A truly awesome widget", category: undefined, tags: undefined }

Explanation: A Product object is created with the specified name, price, and description. Optional properties are undefined.

Example 2:

Input:
builder.setName("Basic Gadget").setPrice(-5).build()

Output:
Error: Price must be a positive number.

Explanation: An error is thrown because the price is negative.

Example 3:

Input:
builder.setPrice(10).build()

Output:
Error: Name is required.

Explanation: An error is thrown because the name is missing.

Constraints

  • The Product and ProductBuilder classes must be defined in TypeScript.
  • The build() method must throw an error if required properties are missing.
  • The price property must be a positive number.
  • The tags property must be an array of strings.
  • The solution should be well-structured and readable.

Notes

  • Consider using TypeScript's type system to enforce type safety and ensure that the builder methods are used correctly.
  • Think about how to handle optional properties in a clean and type-safe way.
  • While immutability isn't strictly required, it's a good practice to make the builder methods return the builder instance itself. This allows for method chaining, which can improve code readability.
  • Focus on creating a robust and type-safe builder that can handle various scenarios.
Loading editor...
typescript