Description
Scenario:
Right now Object.assign() doesn't return a typed Object. And as I see it, it should not return one. The Object.assign() should be use as in plain JS, allowing to shallow merge any typed objects.
Instead, I would suggest the use of a .assign(). This assign() should be a method in the Class object, and not in the instance. This would allow to explicit request and be sure you will only retrieve a typed object with the wanted class, in a way that I find easy to remember and logical to reproduce.
Syntactic:
public static assign(...objs) {
objs = objs.filter(obj => obj !== {} || obj === null || obj === undefined);
return objs
.map(obj => {
// I guess there is a better way to instance an object that assuming and empty constructor.
let newObj = new T();
Object.keys(newObj).forEach(key => {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
};
});
return newObj;
})
.reduce((previus, current) => {
return Object.assign(previus, current);
});
}
Emit:
This emit something like this (got it from the playground):
T.assign = function () {
var objs = [];
for (var _i = 0; _i < arguments.length; _i++) {
objs[_i - 0] = arguments[_i];
}
objs = objs.filter(function (obj) { return obj !== {} || obj === null || obj === undefined; });
return objs
.map(function (obj) {
var newObj = new T();
Object.keys(newObj).forEach(function (key) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
});
return newObj;
})
.reduce(function (previus, current) {
return Object.assign(previus, current);
});
};
Compatibility:
I just test this in the playground, but this is just plain JS to get a typed object.
Other:
- Example code: (used to test it in the Playground)
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
public static assign(...objs) {
objs = objs.filter(obj => obj !== {} || obj === null || obj === undefined);
return objs
.map(obj => {
let newObj = new Greeter('');
Object.keys(newObj).forEach(key => {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
});
return newObj;
})
.reduce((previus, current) => {
return Object.assign(previus, current);
});
}
}
let greeter = new Greeter("world");
greeter = Greeter.assign(
{},
greeter,
{
greeting: 'from Venezuela'
});
let button = document.createElement('button');
button.textContent = "Say Hello";
button.onclick = function() {
alert(greeter.greet());
}
document.body.appendChild(button);
I don't see that this can have any performance issues. I search a little before post this, but I have to recognize, but search was not exhaustive. This can help this #11100, and I think this can help this as well #11150, cause the spread can call it's own Class.assign internally.
I really hope you like this. :). Thanks you for reading.