I'm trying to build a sessionStorage service that can parse objects strings to a generic type. but with this implementation it only returns an object without prototype (no object functions).
here is the code:
public static getObject<T>(key: string): T{
return JSON.parse(sessionStorage.getItem(key)) as T;
}
Regards!
CodePudding user response:
JSON does not encode functions, or prototypes, or constructors. Parsed JSON will never create an instance of any class for you. It's just raw structured data. And this is true for most ways that you might serialize javascript data.
There is no good way around that. It's up to you to structure your codebase so that things will work with this in mind.
There are an innumerable number of solutions to this, but for example you could pass this data to a constructor after you fetch it.
Something like this:
const data = sessionStorageInstance.getObject<MyInterfaceHere>('some/key')
const instance = new MyClassHere(data)
CodePudding user response:
I assume you're using your code somewhat like this?
class SessionStorageManager {
public static getObject<T>(key: string): T{
return JSON.parse(sessionStorage.getItem(key)) as T;
}
}
const test = SessionStorageManager.getObject('test');
In this example, T
has no default value set where getObject
is defined, and I haven't set a type when calling getObject
either, so the type of test
according to TypeScript is unknown
.
If you want to make sure that anything returned by getObject
is a type of Object
, then you'll want to use extends
when creating your generic function to explain this to TypeScript. For example:
public static getObject<T extends object>(key: string): T{
return JSON.parse(sessionStorage.getItem(key)) as T;
}
However, be wary that the use of as
here is essentially bypassing the type check. Only do this if you are confident that you will always be getting an object out of JSON.parse
. Remember that you can still get primitives out of it, in cases such as JSON.parse('2')
or JSON.parse("string")
, and if the JSON string is malformed then JSON.parse
will throw an error.
If you want to be type safe, then you will need to add a type check to support that as
type assertion. Depending on how you are using this code, you might need to do that outside the getObject
function since you might now know what custom type guard may need to be used to determine whether or not an object really is of the given type of T
.
To ensure these type guards must be used, you may want to instead have getObject
return the type unknown
, which means TypeScript won't let you make any assumptions about the type until you've done some type narrowing. For example:
class SessionStorageManager {
public static getObject(key: string): unknown {
return JSON.parse(sessionStorage.getItem(key));
}
}
const obj = SessionStorageManager.getObject('test'); // type unknown
if (typeof obj === 'object') {
// type object
}