The goal: I want to associate a method with an action value passed through the method decorator and keep this action-method map on the instance of the class whose method was decorated. In other words, I want to “register” a method into a “table” where each method is associated with an action value, for example, { "send": sendMessage(), ... }
and do it through the method decorators.
The problem:
When I add a class property for keeping action-method pairs, it’s always empty even when I update it in the decorator. Removing the property “solves” the problem, and the code compiles and runs successfully, but then I lose type checking.
How do I fix this? Is there a better approach?
Here is the working code example and a link to TypeScript Playground:
enum Action {
Send,
Create,
};
function action(action: Action) {
return function <This, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
if (context.kind !== 'method')
throw new Error('This decorator can only be applied to methods.');
context.addInitializer(function () {
if (!this.actionsMap)
this.actionsMap = new Map();
this.actionsMap.set(action, target.bind(this));
});
};
}
class Service {
// Results in an empty map:
// actionsMap: Map<Action, Function> = new Map();
@action(Action.Send)
public sendMessage() {
console.log('Sending message...');
}
@action(Action.Create)
public createMessage() {
console.log('Creating message...');
}
}
const service = new Service();
service.actionsMap.get(Action.Send)();
1