4
votes

I'm using the following code set and get strongly typed item with local storage.

The set works as expected and puts JSON into local storage.

However, when getting the same item out, the casting to the generic type doesn't seem to work. It doesn't cause and exception and just return a JSON string, not the desired typed object.

export class StorageService {
    constructor() { }

    setItem<T>(key: string, item: T): void {
        localStorage.setItem(key, JSON.stringify(item));
    }

    getItem<T>(key: string): T {
        let data: any = localStorage.getItem(key);
        if (!data) return null;

        let obj: T;

        try {
            obj = <T>JSON.parse(data);
        } catch  (error) {
            obj = null;
        }

        return obj
    }
}
2

2 Answers

4
votes

That is because typescript does not have type casting.

It has type assertions.

What obj = <T>JSON.parse(data); does is to tell the compiler that whatever JSON.parse returns it is of type T. It's all at compile time there is nothing at runtime.

If you'd want to have something like this done in a type save manner you'd probably have to implement a standard way to serialize and deserialize your classes. Like a Serializable interface that could transfer the state of class instance to string and a method to create a new object of that type from the serializes state.

1
votes

You can't do this because JSON.parse() returns a new plain JavaScript object as represented by the string input. If you pass an instance of a class (e.g. Person) into your setItem() method, then the value that would be returned by your JSON.parse() in your getItem() method would not be an instance of Person, but rather a plain JavaScript project with all of the properties that were serialized in your setItem() method. You should, however, be able to cast to interfaces, which might be what you want if you are building some kind of strong-typed value persistence module.

See this question & answer: How do I cast a JSON object to a typescript class