# Problem

I am loading things from the localStorage and this has to be saved as json, so it needs to have a simple Object structure to be possible to JSON.parse().

However, som methods do not accept <any> as parameter, because they want a concrete class or interface, but i want to send my object as parameter, so i have to convert it to a Map in order to have the same structure, but seen as it has a type, it is now accepted as parameter.

My problem lies within the conversion from Object to Map

# Solution

public static convertObjectToMap<V>(obj: any, classOfV): Map<string, V> {
let objectMap = new Map<string, V>();
if (obj !== undefined && obj !== null) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
const initObject = new classOfV(obj[key]);
objectMap.set(key, initObject);
}
}
}
return objectMap;
}


I take an obj and the class which all values are going to be in the same type.

# Example of usage

//This is purely for the example
const fibonacciObject:any = {"0": 1, "1": 1, "2": 2, "3": 3, "4": 5};

const fibonacciMap:Map<string, Number> = convertObjectToMap<Number>(fibonacciObject, Number);

fibonacciMap.get("0"); //1
fibonacciMap.get("4"); //5


# Question

Is there a better way to do this conversion, i know about new () => V, but since i need it for each key, then it is not really feasible.

Also what Type would class of V be, i keep getting type errors when i try to give it a Type

A few points first.

1. Avoid any like the plague. You can nearly always figure out a better type. When dealing with a JSON serialized data, I like to have a function similar to this to get rid of any as soon as possible:

function verify<T>(obj: any, fallback: T, isT: (obj: any) => obj is T): T {
return isT(obj) ? obj : fallback;
}

2. Object.keys and Object.entries are a better fit for looping through an object if you are going to check hasOwnProperty. I prefer Object.entries when possible, if you have the browser support.

3. Choose const or let, don't mix them without good reason. const can result in better type inference so I prefer to use it when possible.

Here is how I would implement this function.

function convertObjectToMap<In, Out>(
obj: { [K: string]: In } | undefined | null,
classOfIn: new (v: In) => Out
): Map<string, Out> {
const result = new Map<string, Out>();

for (const [key, val] of Object.entries(obj || {})) {
result.set(key, new classOfIn(val));
}

return result;
}

• What would the generic parameters for In and Out be, and isn't classOfIn(obj[key]) supposed to be classOfIn(val) Feb 3 '18 at 20:56
• Fixed classOfIn, In your example case it would be <number, Number>, but it can be left off since Typescript can infer the type from the classOfIn parameter. Feb 3 '18 at 21:00
• Most of the time In and Out would be the same type though right? Feb 3 '18 at 21:11
• That greatly depends on how you use the function, if you are just using strings and numbers, yes. However this could work with more complex classes. Feb 3 '18 at 21:12
• My constructor for the classes for this looks like this constructor({name, age}){ //Unpacked can be used right away } I would probably not use it for Number, but it was the simplest example i could make up Feb 3 '18 at 21:16