'Decorator isn't getting triggered in typescript project
I have @OnChange
decorator which receives a callback after the value of the property is triggered.
export interface SimpleChange<T> {
firstChange: boolean;
previousValue: T;
currentValue: T;
isFirstChange: () => boolean;
}
export interface CallBackFunction<T> {
(value: T, change?: SimpleChange<T>): void;
}
export function OnChange<T = any>(callback: CallBackFunction<T> | string) {
const cachedValueKey = Symbol('cachedValue');
const isFirstChangeKey = Symbol('isFirstChange');
return (target: any, key: PropertyKey) => {
console.log(`@OnChange called on '${ String(key) }' from '${ target.constructor.name }'`);
const callBackFn: CallBackFunction<T> = typeof callback === 'string' ? target[callback] : callback;
if (!callBackFn) {
throw new Error(`Cannot find method ${ callback } in class ${ target.constructor.name }`);
}
Object.defineProperty(target, key, {
set: function(value) {
this[isFirstChangeKey] = this[isFirstChangeKey] === undefined;
if (!this[isFirstChangeKey] && this[cachedValueKey] === value) {
return;
}
const oldValue = this[cachedValueKey];
this[cachedValueKey] = value;
const change: SimpleChange<T> = {
firstChange: !!this[isFirstChangeKey],
previousValue: oldValue,
currentValue: value,
isFirstChange: () => !!this[isFirstChangeKey]
};
this[isFirstChangeKey] = false;
callBackFn.call(this, this[cachedValueKey], change);
},
get: function() {
return this[cachedValueKey];
}
});
};
}
Here's the class that using it:
export class Component extends BaseComponent {
@OnChange<number>(function (value, changes) {
console.log(value)
})
height: number = 0;
calculateHeight(minHeight, maxHeight, ratio) {
// this not triggering the @OnChange decorator
this.height += 100; // just for demo purposes
}
}
{
"compilerOptions": {
"lib": ["es2018", "DOM"],
"module": "CommonJS",
"target": "ES2020",
"types": ["jest", "node"],
"outDir": "build",
"moduleResolution": "node",
"declaration": true,
"declarationMap": true,
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"esModuleInterop": true,
"inlineSourceMap": true,
"inlineSources": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false,
"plugins": [
{
"name": "tslint-language-service",
"alwaysShowRuleFailuresAsWarnings": false,
"ignoreDefinitionFiles": true,
"disableNoUnusedVariableRule": false,
"supressWhileTypeErrorsPresent": false,
"mockTypeScriptVersion": false
}
]
},
"include": ["src/**/*.ts"]
}
Update:
Seems like the debugger is unable to reach: Object.defineProperty
it simply doesn't see it.
I have other decorator inside this project and it does work as needed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|