add on change decorator

This commit is contained in:
Dan Percic 2021-09-24 19:30:44 +03:00
parent 4f0d8022ed
commit b55e3bf0dd
2 changed files with 61 additions and 0 deletions

View File

@ -0,0 +1,60 @@
import { FunctionKeys } from '../types/utility-types';
export interface SimpleChange<T> {
readonly previousValue: T;
readonly currentValue: T;
readonly isFirstChange: boolean;
}
export type CallBackFunction<T> = (value: T, change: SimpleChange<T>) => void;
type TypedPropertyDecorator<C> = (target: C, key: PropertyKey) => void;
const CACHED_VALUE_KEY = Symbol();
const IS_FIRST_CHANGE_KEY = Symbol();
interface Instance<T> {
[CACHED_VALUE_KEY]: T;
[IS_FIRST_CHANGE_KEY]: boolean;
[key: string]: unknown;
}
export function OnChange<T>(callback: CallBackFunction<T> | string): PropertyDecorator;
// eslint-disable-next-line @typescript-eslint/ban-types
export function OnChange<T, C extends Object = Object>(callback: CallBackFunction<T> | FunctionKeys<C>): TypedPropertyDecorator<C>;
// eslint-disable-next-line @typescript-eslint/ban-types
export function OnChange<T, C extends Object = Object>(callback: CallBackFunction<T> | FunctionKeys<C>): TypedPropertyDecorator<C> {
return function _onChange(target: C, key: PropertyKey) {
Object.defineProperty(target, key, {
set(value: T) {
const instance = this as Instance<T>;
const callBackFn = <CallBackFunction<T>>(typeof callback === 'string' ? instance[callback] : callback);
if (!callBackFn) {
throw new Error(`Cannot find method ${String(callback)} in class ${target.constructor.name}`);
}
instance[IS_FIRST_CHANGE_KEY] = instance[IS_FIRST_CHANGE_KEY] === undefined;
// No operation if new value is same as old value
if (!instance[IS_FIRST_CHANGE_KEY] && instance[CACHED_VALUE_KEY] === value) {
return;
}
const oldValue = instance[CACHED_VALUE_KEY];
instance[CACHED_VALUE_KEY] = value;
const simpleChange: SimpleChange<T> = {
previousValue: oldValue,
currentValue: instance[CACHED_VALUE_KEY],
isFirstChange: instance[IS_FIRST_CHANGE_KEY]
};
callBackFn.call(instance, instance[CACHED_VALUE_KEY], simpleChange);
},
get(): T {
return (this as Instance<T>)[CACHED_VALUE_KEY];
}
});
};
}

View File

@ -8,3 +8,4 @@ export * from './types/tooltip-positions.type';
export * from './decorators/bind.decorator';
export * from './decorators/required.decorator';
export * from './decorators/debounce.decorator';
export * from './decorators/on-change.decorator';