Hone logo
Hone
Problems

Implementing Decorator Types in TypeScript

Decorators are a powerful feature in TypeScript that allow you to modify classes, methods, accessors, and parameters. This challenge focuses on understanding and implementing decorator types, ensuring type safety when using decorators. You'll be crafting decorators that correctly type the decorated elements, demonstrating a strong grasp of TypeScript's advanced type system.

Problem Description

The goal is to implement three different types of decorators in TypeScript: a class decorator, a method decorator, and a parameter decorator. Each decorator should be type-safe, meaning it should correctly infer and maintain the types of the decorated elements. The class decorator should add a property to the decorated class. The method decorator should log a message before and after the decorated method is executed, while preserving the original method's type. The parameter decorator should log the value of the decorated parameter.

Key Requirements:

  • Class Decorator: Takes a class as input and adds a new property named decorated of type boolean initialized to true to the class.
  • Method Decorator: Takes a method as input, wraps it in a function that logs a message before and after the original method's execution, and returns the wrapped function. The returned function must maintain the original method's signature (return type and parameters).
  • Parameter Decorator: Takes a parameter as input and logs the parameter's value when the decorated method is called.

Expected Behavior:

  • The class decorator should modify the class prototype.
  • The method decorator should preserve the original method's type signature.
  • The parameter decorator should log the parameter value without affecting the method's execution or type.
  • All decorators should be type-safe, meaning TypeScript should not report any type errors when using them.

Edge Cases to Consider:

  • Decorating methods with different return types.
  • Decorating methods with optional parameters.
  • Decorating methods with rest parameters.
  • Decorating classes that extend other classes.

Examples

Example 1: Class Decorator

Input:
class MyClass {
  greet() {
    return "Hello";
  }
}

@decorateClass
class DecoratedClass extends MyClass {}

Output:
DecoratedClass {
  greet: () => string;
  decorated: boolean;
}
Explanation: The `DecoratedClass` now has a `decorated` property set to `true`.

Example 2: Method Decorator

Input:
class MyClass {
  @decorateMethod
  myMethod(name: string): string {
    return `Hello, ${name}!`;
  }
}

Output:
MyClass {
  myMethod: (name: string) => string;
}
Explanation: When `myMethod` is called, a message is logged before and after execution, but the return type remains `string`.

Example 3: Parameter Decorator

Input:
class MyClass {
  @decorateParameter
  myMethod(name: string): string {
    return `Hello, ${name}!`;
  }
}

Output:
MyClass {
  myMethod: (name: string) => string;
}
Explanation: When `myMethod` is called with a `name` argument, the value of `name` is logged to the console. The method's signature remains unchanged.

Constraints

  • All decorators must be implemented using TypeScript's decorator syntax.
  • The code must be type-safe and free of TypeScript errors.
  • The decorators should be generic enough to handle various class, method, and parameter types.
  • The logging in the method and parameter decorators should be done using console.log.

Notes

  • Consider using type inference to ensure the decorators are type-safe.
  • The decorators should not modify the original class or method definitions beyond what is specified in the problem description.
  • Think about how to preserve the original method's signature when wrapping it with the method decorator. This is crucial for type safety.
  • The parameter decorator should not affect the method's execution flow. It should only log the parameter value.
Loading editor...
typescript