Search code examples
angulartypescriptconstants

const value changing when variable accessing that const is updated in angular/typescript


This is stackblitz demo (not exact but somewhat idea of what problem I am trying to tell)

I have defined a const in src/app/constants/app.ts

export const DEFAULT_FILTERS = {
    "page":1,
    "perPage":10,
    "sortOrder": "asc",
    "tag":"all",
    "sortBy":"firstname"
}

I have done this to remove clutter from different interconnected components where I need to define filters as a variable and then using it.

listing.component.ts

import { DEFAULT_FILTERS} from '@app/constants/app';

export class listingComponent implements OnInit, OnDestroy {

    private for = someOtherconstant; // some other const used here.

    private params = {
        "filters": DEFAULT_FILTERS,
        "for": this.for
    }

    getNewRecords(pageNum) {
        console.log('default filters', DEFAULT_FILTERS)
        this.currentPageNum = pageNum;
        this.params['filters']['page'] = this.currentPageNum; 
        this._service.triggerCallForUsersObservable(this.careGroupParams)
    }
}

The console.log inside getNewRecords prints DEFAULT_FILTERS which I have changed no where still the page index inside DEFAULT_FILTERS because I am changing this.params['filters']['page'] = this.currentPageNum. Why?

I need a global const which I want to keep const for diff components so that I can reset the filters value whenever required.

EDIT:

If I use object.freeze then I am not able to change the property this.params like:

this.params['filters']['name'] = 'xyz'

So what could be the other way to keep DEFAULT_FILTER as global variable/const and then I can access it or change it and change the new variable which is accessing it but not the global val?


Solution

  • You can copy the const value instead of referencing it. However, as soon as you copy, it loses the connection with the original value; nonetheless, as it is a const value, it is not supposed to be changed, so it wouldn't be a problem.

    You can copy the object by using the ... (spread) operator like the code bellow:

    private params = {
        "filters": { ...DEFAULT_FILTERS },
        "for": this.for
    }
    

    Alternatively, you can create a class with a static property getter that always return a fresh object so there is no risk of losing the original value.

    class Constants {
      static get DEFAULT_FILTERS() {
        return {
          "page": 1,
          "perPage": 10,
          "sortOrder": "asc",
          "tag": "all",
          "sortBy": "firstname"
        }
      }
    }
    
    let myDefaultFilter = Constants.DEFAULT_FILTERS;
    myDefaultFilter.page = 2;
    Constants.DEFAULT_FILTERS.page = 3; // forcing changes
    
    console.log(myDefaultFilter.page) // changes
    console.log(Constants.DEFAULT_FILTERS.page) // stays the same