Typescript Decorator
Decorator Workflow
flowchart TD
A[Decorator Definition] --> B{Decorator Type}
B -->|Class Decorator| C1[Modify Class Constructor]
B -->|Method Decorator| C2[Modify Method Behavior]
B -->|Property Decorator| C3[Modify Property Access]
B -->|Parameter Decorator| C4[Modify Parameter Metadata]
C1 --> D1[Wrap/Extend Class Functionality]
C2 --> D2[Modify Method Execution]
C3 --> D3[Add Validation/Transformation]
C4 --> D4[Add Metadata/Validation]
D1 --> E1[Runtime Class Modification]
D2 --> E2[Intercept Method Calls]
D3 --> E3[Control Property Get/Set]
D4 --> E4[Enhance Method Signatures]
E1 --> F1[Additional Capabilities]
E2 --> F2[Logging/Performance Tracking]
E3 --> F3[Validation/Transformation]
E4 --> F4[Dependency Injection]
F1 --> G[Apply to Target]
F2 --> G
F3 --> G
F4 --> G
G --> H[Runtime Execution]
H --> I{Conditions Met?}
I -->|Yes| J[Execute Original Behavior]
I -->|No| K[Handle/Modify Behavior]
J --> L[Return Result]
K --> L
Decorator Composition
Multiple decorators can be applied to a declaration, for example on a single line:
Declare a Decorator Factory
function ActualDecorator(
target: any, // (1)
propertyKey: string, // (2)
descriptor: PropertyDescriptor) { // (3)
...
}
targetThe target is the constructor function if we apply the decorator to a static member and the prototype of the class if it is applied on an instance property.propertyKeyis the name of the decorated method, example:adddescriptoris the property descriptor of that method.
Decorator Evaluation order:
- Parameter Decorators, followed by Method, Accessor, or Property Decorators are applied for each instance member.
- Parameter Decorators, followed by Method, Accessor, or Property Decorators are applied for each static member.
- Parameter Decorators are applied for the constructor.
- Class Decorators are applied for the class.
class decorator
Method Decorators
descriptor.valueis aFunctioninterface,descriptor.value.toString()=>descriptor.valueis the decorated function that will be called. when the function is called,argswill be passed in.performanceis from Performance API. which provides high-resolution timestamps and methods to measure the performance of your codeperformance.now()gives the time relative to the time the page or Node.js process started.
Accessor Decorator
Property Decorator
Parameter Decorator
Examples:
(1): Log Method Debug Info
write a method decorator that logs the method name, arguments, and return value of the method, and its execution time.
(2) Min Field Length
Implement a property decorator @MinLength(len: number) that ensures a string property has at least len characters.
// Demonstration of different scenarios
console.log("--- Scenario 1: Valid Username ---");
try {
const user = new User("johndoe");
console.log(`Created user with username: ${user.username}`);
} catch (error: any) {
console.error(error.message);
}
console.log("\n--- Scenario 2: Invalid Username ---");
try {
const user = new User("john");
} catch (error: any) {
console.error(error.message);
}
console.log("\n--- Scenario 3: Changing Username After Creation ---");
try {
const user = new User("johndoe");
console.log(`Initial username: ${user.username}`);
// Attempt to change username
user.username = "a";
} catch (error: any) {
console.error(error.message);
}
[Decorator Factory] MinLength called with length: 5
[Decorator] Applied to target: {}
[Decorator] Property key: username
[Property Definition] Defining property with custom descriptor
--- Scenario 1: Valid Username ---
[Constructor] Creating user with username: johndoe
[Setter] Attempting to set value: johndoe
[Validation] Length check passed
[Getter] Retrieving value: johndoe
Created user with username: johndoe
--- Scenario 2: Invalid Username ---
[Constructor] Creating user with username: john
[Setter] Attempting to set value: john
[Validation] Length check failed
username must be at least 5 characters long
--- Scenario 3: Changing Username After Creation ---
[Constructor] Creating user with username: johndoe
[Setter] Attempting to set value: johndoe
[Validation] Length check passed
[Getter] Retrieving value: johndoe
Initial username: johndoe
[Setter] Attempting to set value: a
[Validation] Length check failed
username must be at least 5 characters long