Skip to content

Instantly share code, notes, and snippets.

@siandreev
Created October 20, 2021 11:38
Show Gist options
  • Save siandreev/a07b6cb1b44f3b4e64161233eb307c78 to your computer and use it in GitHub Desktop.
Save siandreev/a07b6cb1b44f3b4e64161233eb307c78 to your computer and use it in GitHub Desktop.
PropertyDecorator
function OnChange<ClassT, T>(callback: (ClassT, T) => void): any {
return (target: Object, propertyKey: string | symbol) => {
const symbolKey = Symbol(propertyKey.toString());
// Необходимо задействовать существующий дескриптор, если он есть.
// Это позволит объявять несколько декораторов на одном свойстве.
const descriptor = Object.getOwnPropertyDescriptor(target, propertyKey)
|| {configurable: true, enumerable: true};
// Подменяем или объявляем get и set
const originalGet = descriptor.get || function() {
return this[symbolKey];
};
const originalSet = descriptor.set || function(val) {
this[symbolKey] = val;
};
descriptor.get = originalGet;
descriptor.set = function(newVal: T) {
// Определяем set через function, чтобы не потерять this
const currentVal = originalGet.call(this);
if (newVal != currentVal) {
callback.call(target.constructor, this, newVal);
}
originalSet.call(this, newVal);
};
// Объявляем новое свойство, либо обновляем дескриптор
Object.defineProperty(target, propertyKey, descriptor);
// Необходимо переопределить дескриптор и вернуть его
// из-за бага в reflect-metadata
return descriptor;
}
}
class User {
@OnChange(User.onNameChange)
public name = 'unknown';
public age: number;
static onNameChange(instance: User, newValue: string): void {
console.log('Changing from', instance.name, 'to', newValue);
}
}
const user = new User();
user.name = "NewName"
user.age = 12;
console.log("user.hasOwnProperty('name'):", user.hasOwnProperty('name'));
console.log("user.hasOwnProperty('age'):", user.hasOwnProperty('age'));
const user2 = new User();
user2.name = 'No';
user2.age = 10;
console.log('user.name:', user.name);
console.log('user.age:', user.age);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment