Issue with TypeScript Decorators: Setter function is not being invoked for an object's property

I am working on incorporating TypeScript Decorators in an Angular application to store data in local storage. This is my current goal:

export function Storage() {
    return function (target, key): any {
        // property value
        let _val = target[key];

        // property getter
        const getter = function () {
            const data = localStorage.get(key);
            if (data) {
                return data;
            }
            localStorage.set(key, _val);
            return _val;
        };

        // property setter
        const setter = function (newVal) {
            localStorage.set(key, newVal);
            console.log('Setting', newVal);
            _val = newVal;
        };

        // Create new property with getter and setter
        Object.defineProperty(target, key, {
            configurable: true,
            enumerable: true,
            get: getter,
            set: setter
        });
    };
}

And here is how you can use it:

Component 1:
....
@Storage() userSession: any = {val: ''};

ngOnInit() {
    this.userSession.val = "some value"
}
....

Component 2:

....
@Storage() userSession: any;

ngOnInit() {
    console.log('Stored value is', this.userSession);
    // expected: {val: 'some value'}
    // prints: {val: ''}
}
....

Based on my understanding, the property setter is only triggered when there is any assignment to the object itself, not its property. This is why the suggested method works:

Object.assign(this.userSession, {val: 'some value'});
or
this.userSession = {val: 'some value'}

console.log(this.userSession) // prints: {val: 'some value'}

However, this defeats the purpose I am aiming for. Therefore, my question is, how can I modify the decorator function to allow for this syntax?

this.userSession.val = 'some value';

Any guidance would be greatly appreciated.

Answer №1

Although I haven't utilized decorators in this particular manner, my understanding is that deleting the property is necessary to replace it. Therefore, make the following adjustment:

    Object.defineProperty(target, key, {
        get: getter,
        set: setter,
        enumerable: true,
        configurable: true
    });

Transform it by adding a delete action:

if (delete this[key]) {
    Object.defineProperty(target, key, {
        get: getter,
        set: setter,
        enumerable: true,
        configurable: true
    });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on mocking a function inside another function imported from a module with TypeScript and Jest

I have a function inside the action directory that I want to test: import { Action, ActionProgress, ActionStatus, MagicLinkProgress } from '../../interfaces' import { areSameActions } from '../actionsProgress' export const findActionPr ...

Increase by 30 minutes from the minimum value and decrease by 30 minutes from the maximum value in Ionic date time

Looking to add a customized Ionic date time picker with min and max capabilities. If the minimum time is selected, it should automatically add 30 minutes, while selecting the maximum time should subtract 30 minutes. Any suggestions on how to achieve this? ...

A guide on updating an Observable with a value retrieved from another Observable

Struggling to find a way to update the result of one Observable with the result of another. Can anyone provide guidance on how to do this without nested subscriptions and return the resulting Observable for later use? this._http.get<JSON>(url, { pa ...

Having difficulty pushing code from the Vs Code interface to gitlab. Receiving error message "Git: [email protected]: Permission denied (publickey, keyboard-interactive)"

Being a Mac user, I've encountered an issue where my VS Code connection to GitLab seems incomplete. While I am able to commit code using the VS Code interface, I struggle with pushing the code to the repository directly from VS Code. Instead, I resort ...

Troubleshooting asynchronous problems with rxjs chaining within ngrx effects

@Effect({ dispatch: false }) public setJwtDataParcoursPage = this.actions$.pipe( ofType(INIT_FORM_SUCCESS_ACTION), map((action: InitFormSuccessAction) => action.payload), withLatestFrom(this.store.select(this._apiHeadersSelector.getJwt) as Observa ...

Looking to address excessive re-renders caused by Redux on a single page and seeking assistance in identifying and resolving the problem

Currently, I am in the process of developing the dashboard website for a music theory application company. This platform will allow users to manage various aspects such as their personal information, courses, assignments, and media content. The dashboard ...

The Angular Compiler was identified, however it turned out to be an incorrect class instance

Although this question has been asked before, I have exhausted all possible solutions that were suggested. Unfortunately, I still cannot resolve it on my own. Any assistance would be greatly appreciated. Error: ERROR in ./src/main.ts Module build failed: ...

Transmitting occasional feedback from ASP.NET Web API function to jQuery AJAX

I am currently working on a project that requires sending intermittent status responses from a Web API method back to a jQuery AJAX call in order to display progress in the UI. https://i.sstatic.net/Y6R4w.png The process involves the jQuery AJAX calling ...

What is the most efficient method to iterate through Angular 4 using Bootstrap columns?

I'm trying to arrange my list into different columns using Bootstrap. The first row should have three columns The second row should have two columns The third row should have only one column Here is the code I have: <div *ngFor="let watch of L ...

The system couldn't locate the module: Issue: Unable to find module 'fs' within the directory

I am currently working on integrating the ADAL JS sample code from this link into a SharePoint framework client web part. My code is fairly straightforward, as I have already installed packages like adal, fs, and node-fs using NPM. However, when running t ...

Linking interconnected RxJs observables?

Currently, I am attempting to link observables together that rely on API calls (which are dependent on data from previous observables) in order to create an object. My process involves retrieving a roster that contains a manifest ID. Using that ID, I then ...

How to disable typescript eslint notifications in the terminal for .js and .jsx files within a create-react-app project using VS Code

I'm currently in the process of transitioning from JavaScript to TypeScript within my create-react-app project. I am facing an issue where new ESLint TypeScript warnings are being flagged for my old .js and .jsx files, which is something I want to avo ...

iterating over a nested map within a map in an Angular application

I wrote a Java service that returns an observable map<k, map<k,v>> and I'm currently struggling to iterate through the outer map using foreach loop. [...] .then( (response: Package) => { response.activityMap.forEach((key: s ...

Error: No routes found in Angular 5

I have developed an Angular 5 app and set up the following routing configuration in app-routing.module.ts file: import { ControlPanelComponent } from './dashboard/control-panel/control-panel.component'; import { MainComponent } from './dash ...

Creating Angular Components Dynamically through API Requests

Generating Component Template and Typescript Code Dynamically I am attempting to dynamically create a component where an HTTP service call provides us with the HTML template and Typescript code. While we can set the HTML template dynamically, I am facing ...

Tips for building a versatile client-server application with separate codebases for the JavaScript components

We are embarking on the process of rebuilding our CMS and leveraging our expertise with VueJS. Despite our familiarity with VueJS, we won't be able to create a full single-page application due to the presence of server-side rendering files (JSP). The ...

Exclude the header HTML when exporting data to a file with jQuery DataTables

I've encountered a problem with my simple data table. I added a custom tool-tip div in the datatable for the headings, following this reference. However, when I export the file to excel or PDF, the tooltip text is also included in the exported file. ...

Is there a way to receive additional assistance?

Feeling a bit embarrassed, I must confess that I have just spent a considerable amount of time resolving the frustrating issue: **Syntax Error: Unexpected token <** The reason for this error was that I had overlooked adding the following line to my in ...

I suggest installing the ng2-search-filter package for easy search functionality

Is there a recommended alternative to ng2-search-filter? I encountered an error with this one: 'Ng2SearchPipeModule' does not appear to be an NgModule class.(-996002). The error message in ng2-filter.module.d.ts(1, 22) suggests that the library ( ...

The @angular/fire package is unable to locate the AngularFireModule and AngularFireDatabaseModule modules

I am facing some challenges while trying to integrate Firebase Realtime Database into my Angular project. Specifically, I am encountering difficulties at the initial step of importing AngularFireModule and AngularFireDatabaseModule. To be more specific, I ...