There are 3 primary methods of "mixing" javascript objects.
The process your looking to achieve is called a "mixin".
The older and more widely used method is to use whats called an extend function.
There are many ways to write an extend function, but they mostly look something like this:
const extend = (obj, mixin) => {
Object.keys(mixin).forEach(key => obj[key] = mixin[key]);
return obj;
};
here "obj" is your first object, and "mixin" is the object you want to mix into "obj", the function returns an object that is a mix of the two.
The concept here is quite simple. You loop over the keys of one object, and incrementally assign them to another, a little bit like copying a file on your hard drive.
There is a BIG DRAWBACK with this method though, and that is any properties on the destination object that have a matching name WILL get overwritten.
You can only mix two objects at a time, but you do get control over the loop at every step in case you need to do extra processing (See later on in my answer).
Newer browsers make it somewhat easier with the Object.Assign call:
Object.assign(obj1, mix1, mix2);
Here "obj1" is the final mixed object, and "mix1", "mix2" are your source objects, "obj1" will be a result of "mix1" & "mix2" being combined together.
The MDN article on "Object.Assign" can be found here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Like the extend function above "Object Assign" WILL overwrite properties in the destination object, but it does have the advantage of doing many at a time. My example above only shows 2 "mix" objects, but you can in theory have as many as you like, and that comes in really useful when you have them all in array as you have.
In an array you can either map the objects into one function, and then use the spread operator available in newer browsers, or you can use for..in to loop over the collection.
If your using JQuery, you can use it's foreach method, and underscore.js has dozens of ways of looping.
Since your using TypeScript you can also combine a lot of this with typescripts looping operators too.
There is a 3rd way of merging objects, it's not widely used but it is gaining traction, and that's the "Flight-Mixin" approach that uses the Array prototype, it looks something like this:
const EnumerableFirstLast = (function () { // function based module pattern.
const first = function () {
return this[0];
},
last = function () {
return this[this.length - 1];
};
return function () { // function based Flight-Mixin mechanics ...
this.first = first; // ... referring to ...
this.last = last; // ... shared code.
};
}());
EnumerableFirstLast.call(Array.prototype);
The idea here is that the two objects all ready have the functionality you require on them, so instead of "mixing" them, your just providing a single interface that delegates to them behind the scenes.
Beacuse your adding to the array prototype, you can now do things like the following:
const a = [1, 2, 3];
a.first(); // 1
a.last(); // 3
This might seem as if it's of no use, until you consider what you've in effect just done is added two new functions to a datatype you cannot normally control, this MIGHT if applied to your own objects allow you to add functions dynamically, that simply just grab the values you need to merge in a loop without too much trouble, it would however require a bit of extra planning which is why I'm adding this as more of an idea for further exploration rather than part of the solution.
This method is better suited for objects that are largely function based rather than data based as your objects seem to be.
Irrespective of which mixin method you use though, you will still need to iterate over your array collection with a loop, and you will still need to use spread to get all the keys and properties in one place.
If you consider something like
const myarr = [
{name: "peter", surname: "shaw"},
{name: "schagler", surname: "kahn"}
]
The way the spread operator works is to bust those array entries out into individual parts. So for example, IF we had the following function:
function showTwoNames(entryOne, entryTwo) {
console.log(entryOne.name + " " + entryOne.surname);
console.log(entryTwo.name + " " + entryTwo.surname);
}
You could call that function with the spread operator as follows:
showTwoNames(...myarr);
If your array had more than 2 entries in it, then the rest would be ignored in this case, the number of entries taken from the array is directly proportional to the number of arguments for the function.
You could if you wanted to do the following:
function showTwoNames(entryOne, entryTwo, ...theRest) {
console.log(entryOne.name + " " + entryOne.surname);
console.log(entryTwo.name + " " + entryTwo.surname);
console.log("There are " + theRest.length + " extra entries in the array");
}
Please NOTE that I'm not checking for nulls and undefined or anything here, it should go without saying that you should ALWAYS error check function parameters especially in JavaScript/TypeScript code.
The spread operator can in it's own right be used to combine objects, it can be simpler to understand than other methods like "ObjectAssign" beacuse quite simply you use it as follows:
var destination = { ...source1, ...source2, ...source3); // for as many sources as needed.
Like the other methods this will overwrite properties with the same name.
If you need to preserve all properties, even identically named ones, then you have no choice but to use something like an extend function, but instead of just merging directly using a for-each as my first example shows, you'll need to examine the contents of "key" while also looking in the destination to see if "key" exists and renaming as required.
Update RE: the OP's updates
So being the curious kind I am, I just tried your updated notes on one of my Linux servers, Typescript version is 3.8.3, Node is 12.14.1 and it all seems to work just as you expect it to:

I'm using all the latest versions, so it makes me wonder if your problem is maybe a bug in an old version of TS, or a feature that has only just been added in the newest build and is not present in the version your using.
Maybe try an update see what happens.