Reputation: 2488
I've been experimenting Typescript Decorators recently to try solving a "problem" I have within my application. I'm using a JS bridge to feed TS code to both Android and iOS, and at the moment we declare functions like this:
index.js
import foo from './bar'
global.App = function() {
this.foo = foo;
};
The above will make the foo
function to be available on the native side of the bridge
I wanted to write a decorator to apply on that foo
method which would "register" itself on the global.App
but I've failed in that task.
Here's the decorator that works:
export const Task = (target, propertyKey, descriptor) => {
let originalMethod = descriptor.value;
descriptor.value = (...args) => originalMethod.apply(target, args);
if (!global.App) {
global.App = function () {
this.foo = descriptor.value;
};
}
return descriptor;
}
How could I add another method to that global.App
function?
Upvotes: 2
Views: 116
Reputation: 2488
After wandering around SO for some time I've found a workaround for this... perhaps I lack the knowledge of TS/JS to know exactly what I wanted to do here, but anyways, my solution was to register every task decorated and then on the index.js
I get those tasks and register them on the global.App
function.
Something like this
task.ts
export const TaskRegistry = {};
export const Task = (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = (...args) => originalMethod.apply(target, args);
TaskRegistry[propertyKey] = descriptor.value;
return descriptor;
};
index.js
// eslint-disable-next-line func-names
global.App = function () {
// eslint-disable-next-line consistent-this
const self = this;
Object.keys(TaskRegistry).forEach((key) => {
self[key] = TaskRegistry[key];
});
}
Upvotes: 1
Reputation: 335
Firstly, the foo
method is only added once because the first time the decorator is called global.App
is defined and the branch that adds foo
to global.App
is never re-entered.
Secondly, global.App
and foo
would be overwritten each time and not maintained through repeated calls to the decorator.
Adding another branch that handles adding the method after the first call and dynamically assigns the name of the method, which I believe is given to the decorator in propertyKey
, would permit multiple methods to be added.
export const Task = (target, propertyKey, descriptor) => {
let originalMethod = descriptor.value;
descriptor.value = (...args) => originalMethod.apply(target, args);
if (!global.App) {
global.App = function () {
this[propertyKey] = descriptor.value;
};
} else {
global.App[propertyKey] = descriptor.value;
}
return descriptor;
}
Something like this might work.
Upvotes: 1