Skip to content

Instantly share code, notes, and snippets.

@SoEasy
Created September 26, 2017 14:52
Show Gist options
  • Save SoEasy/1a256f60a05a43a12d4097699c61a7f4 to your computer and use it in GitHub Desktop.
Save SoEasy/1a256f60a05a43a12d4097699c61a7f4 to your computer and use it in GitHub Desktop.
Decorate property, save metadata, receive metadata after constructor, redefine properties
const protoStore = new WeakMap();
function protoKeys(target) {
let retKeys = [];
while(target.__proto__) {
const pKeys = protoStore.get(target.__proto__);
if (pKeys) {
retKeys = [...retKeys, ...protoStore.get(target.__proto__)];
}
target = target.__proto__;
}
return retKeys;
}
function validatable(target) {
const original = target;
function construct(constructor, args) {
const c: any = function() {
return constructor.apply(this, args);
};
c.prototype = constructor.prototype;
return new c();
}
const f : any = function(...args) {
console.log("New: " + original.name);
console.log(protoKeys(this))
const instance = construct(original, args);
const values = {};
for (const propertyKey of protoKeys(this)) {
values[propertyKey] = instance[propertyKey];
Object.defineProperty(instance, propertyKey, {
enumerable: true,
configurable: true,
get: () => values[propertyKey],
set: function(v) {
values[propertyKey] = v;
console.log('in setter', this);
}
})
}
console.log(values);
return instance;
};
f.prototype = original.prototype;
return f;
}
function decorate() {
return function(target, propertyKey) {
const keys = protoStore.get(target) || [];
keys.push(propertyKey);
protoStore.set(target, keys);
}
}
class Base {
@decorate()
phone: string = 'foo';
}
@validatable
class T extends Base {
@decorate()
foo: string = 'bar';
}
class D {
get foo() {
return 1;
}
}
const t = new T();
t.foo = 1;
t.phone = 2;
const t1 = new T();
t1.foo = 2;
t1.phone = 3;
console.log(t.phone, t1.phone);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment