Search code examples
angulartypescripttype-assertion

Type assertion is not working after parsing from local storage


In my angular project I stored an array of data points in the local storage.

For the data I created a class like so:

export class Datapoint {
  id: number;
  name: string;
  // ... some more properties.

  constructor(){
  }

  public getDescription() {
    // ... logic
  }

  // ... more functions
}

Now I retrieve the array from the local storage and parses it back from string.

const dpList = JSON.parse(localStorage.getItem('datapoints'));

Because 'dpList' is of type 'Object' I make a type assertion to my type 'Datapoint'.

const datapoints: Datapoint[] = [];

public someFunction(): Datapoint[] {
  // Get the stringified objects from the local storage.
  const dpList = JSON.parse(localStorage.getItem('datapoints'));

  // Iterate through the array and push to this.datapoints.
  dpList.forEach(dp => {
    const asserted_dp: Datapoint = (dp as Datapoint);
    this.datapoints.push(asserted_dp);
  });
}

But the asserted_dp is after the type assertion of type Object and not Datapoint as I expected it would be. And so I can't access the functions of type Datapoint because the proto property has no information about them.

How can I get the type assertion to work?

Thanks in advance!


Solution

  • Understanding the Issue

    Local storage only stores strings. While you may have stringified your Datapoint objects for storage, when you JSON.parse the string, it doesn't return an instance of Datapoint, instead it gives you a normal javascript Object type. This is important because your object no longer has your Datapoint methods such as getDescription, so you can't just cast the type.

    Potential solution

    I would recommend creating a loader that reconstructs instances of your Datapointfrom your serialized string. I don't know how you normally construct your data points but I'll give a simple example here

    function loadDatapoints(): Datapoint[] {
        var dp_objects: any = JSON.parse(localStorage.getItem('datapoints'));
        var points: Datapoint[] = [];
    
        for (var i: number = 0; i < dp_objects.length; i++) {
            var point: Datapoint = new Datapoint();
            // However you normally construct Datapoints...
            points.push(point);
        }
    
        return points;
    }
    

    This way you're actually working with Datapoint instances and therefore type assertion now work as expected.