Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map array of object to another array with different object in typescript

Tags:

typescript

If i have something like

array1: string[] = ['foo', 'bar'];

and an interface like

export interface MyObject { name: string; }

how can I map array1 to another array of type MyObject?

array2 : MyObject[];
array2 = array1.map(s => ...);

I thought about something like

array2 = array1.map<MyObject>(s => new MyObject(...));
like image 788
rst Avatar asked Jan 24 '19 17:01

rst


People also ask

How do you map an array of objects to another array of objects?

To convert an array of objects to a Map , call the map() method on the array and on each iteration return an array containing the key and value. Then pass the array of key-value pairs to the Map() constructor to create the Map object.

How do I convert one object to another object in TypeScript?

The Typescript generally it converts one data type to another data type by using the cast operation. We can convert all types of datas are converted from one type to another type like that cast object is one of the features for to convert the object type of values to another type.


1 Answers

This is usually where I digress into a long lecture about the difference between types and values in TypeScript, but here I'll try to make it short: since MyObject is only known to be a type and not a constructor value, you can't call new MyObject(). Instead, if you want to make a value of type MyObject, you can just use a plain old object of the right shape, such as via object literal notation:

const myObject: MyObject = {name: "Alice"}; // no error

So your map function can be the following:

const array2: MyObject[] = array1.map(s => ({name: s})); // no error

Simple, right?

Uh, well, please note as in the comments above that the parentheses around {name: s} are necessary, because for better or worse, JavaScript parsers interpret arrow functions of the form (x => {...}) as having a block body where the stuff inside the curly braces are statements. And when you interpret name: s as a statement it means that name is a label, and s is just a string expression statement with the optional semicolon omitted. Interpreted as a function body, {name: s} just evaluates s and doesn't return a defined value (it is void, which is essentially the same as undefined), which is why you get the following weird error if you leave out the parentheses:

let array2: MyObject[] = array1.map(s => { name: s }); // error!
// Type 'void[]' is not assignable to type 'MyObject[]'.
// at runtime, array2 will be [undefined, undefined] which is not what you wanted 🙁

JavaScript parsing is a bit tricky this way. Adding the parentheses to make s => (...) fixes it. Now the stuff after the arrow can only be interpreted as a concise body... that is, a single expression. And interpreting ({name: s}) as an expression yields the object literal that we wanted.

Yay, I avoided writing a book about types and values and somehow ended up writing a different book about expressions and statements. Oh well.

Hope that helps you. Good luck!

like image 147
jcalz Avatar answered Nov 16 '22 06:11

jcalz