Hone logo
Hone
Problems

Property Decorators in TypeScript: Validation and Transformation

Property decorators are a powerful feature in TypeScript that allow you to modify or enhance class properties. This challenge will guide you in creating decorators that both validate and transform property values, ensuring data integrity and consistency within your classes. Understanding and implementing property decorators is crucial for building robust and maintainable TypeScript applications.

Problem Description

You are tasked with creating two property decorators: validateEmail and uppercaseString. The validateEmail decorator should ensure that a string property contains a valid email address format. The uppercaseString decorator should convert a string property to uppercase upon assignment.

What needs to be achieved:

  • Implement the validateEmail decorator to check if a string property conforms to a basic email format (e.g., contains "@" and "."). It should throw an error if the validation fails.
  • Implement the uppercaseString decorator to automatically convert the value of a string property to uppercase when it's assigned.
  • Apply both decorators to a sample class demonstrating their functionality.

Key Requirements:

  • The decorators must be reusable and applicable to any string property.
  • The validateEmail decorator must throw an Error object with a descriptive message if the email format is invalid.
  • The uppercaseString decorator must not affect the original value; it should only modify the property's value.
  • The decorators should be implemented using TypeScript's decorator syntax.

Expected Behavior:

  • When a property decorated with validateEmail is assigned an invalid email address, an error should be thrown.
  • When a property decorated with uppercaseString is assigned a string, the property should store the uppercase version of that string.

Edge Cases to Consider:

  • What happens if the property is not a string? (The decorators should ideally handle this gracefully, perhaps by doing nothing or throwing a different error.)
  • What happens if the property is already initialized before the decorator is applied? (Consider how to handle existing values.)
  • Consider the order in which decorators are applied. Does it matter?

Examples

Example 1:

Input:
class User {
  @validateEmail
  email: string = "invalid-email";
}

const user = new User();

Output:

Error: Invalid email format.

Explanation: The validateEmail decorator detects the invalid email format and throws an error during instantiation.

Example 2:

Input:
class Product {
  @uppercaseString
  name: string = "product name";
}

const product = new Product();
console.log(product.name);

Output:

PRODUCT NAME

Explanation: The uppercaseString decorator converts the initial value of the name property to uppercase.

Example 3: (Edge Case)

Input:
class Settings {
  @validateEmail
  configEmail: string | number = 123;
}

const settings = new Settings();

Output:

(No error thrown, or a more specific error indicating a non-string type)

Explanation: The decorator should handle the case where the property is not a string gracefully. Ideally, it would either do nothing or throw an error indicating the incorrect type.

Constraints

  • The email validation should be a basic check (presence of "@" and "."). Complex regex validation is not required.
  • The decorators must be implemented using TypeScript's decorator syntax.
  • The code should be well-structured and readable.
  • The validateEmail decorator must throw an Error object.

Notes

  • Remember that decorators are essentially functions that modify classes, methods, or properties.
  • The validateEmail decorator should be applied before the property is assigned a value.
  • Consider using TypeScript's type system to ensure type safety within your decorators.
  • Think about how to handle properties that are already initialized when the decorator is applied. You might need to check if the property already has a value before applying the transformation.
Loading editor...
typescript