Created
October 20, 2021 11:38
-
-
Save siandreev/a07b6cb1b44f3b4e64161233eb307c78 to your computer and use it in GitHub Desktop.
PropertyDecorator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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