Issue
I have a situation where I have defined three model classes as below
export class Parent
{
name: string;
containers: Container[];
}
export class Container
{
desc: string;
sets: Sets[];
}
export class Sets
{
private _data?: any[];
private _dataSet?: any[];
get data()
{
if (this.dataSet && this.dataSet.length > 0)
{
return this._dataSet[0].data;
}
return this._data;
}
set data(data: any[])
{
this._data = data;
}
get dataSet()
{
return this._dataSet;
}
set dataSet(dataSet: any[])
{
this._dataSet = dataSet;
}
}
The problem is: the getter and setter method of Set class wouldn't get triggered unless I do new Set() explicitly (I don't know if the new Set() this is really necessary).
For example:
"name": "vik",
"containers": [
{
"desc": "something",
"sets": [
{
"dataSet": [
{
"data":[
{
// Object
}]
}]
}]
}]
When i do:
let response:Parent = responseObj;
console.log(response.containers[0].sets[0].data)
it should return the DataSet value, but instead it returns undefined.
But if i do:
let response:Parent = responseObj;
console.log(new Sets(response.containers[0].sets[0]).data)
returns me the correct value.
Did I miss something or how could I improve my code so it works?
Solution
The problem is that your object comes from HTTP. What does this mean:
Http is a text based format. This means that when response comes to you it is an only string like:
"{"foo":"boor"}"
Then you do smth like JSON.parse(data) and return real object like:
{foo: "bar"};
But JSON.parse does no nothing about type you expected. It doesn't know how to make from string instance of the object. It can just try to make a simple object and this is all.
You see, your data object has no information about it's type, methods, getter/setters e.t.c. It is just about plane data aka dto. So, if you want to get real classes from your dto you should write smarter parser, that will take your dto and create from it real instance of the expected class. Basically you already do this by
new Sets(response.containers[0].sets[0])
So you can keep doing this, but than you will find that this repetitive code is all around your application. The best way I found is to inject mapper to the data server and return not dto but an instance. So your other code will no nothing about this "dirty" work and will always works with "normal" objects.
Hope this helps.
UPD:
const rawData = '{"name":"Vitalii"}';
const person1 = JSON.parse(rawData);
function Person({name}) {
this.name = name;
this.say = function() {
console.log(`Hi, ${this.name}`);
}
}
let person2 = new Person(person1);
person2.say();
// person1 and person2 have the same data inside. But:
console.log(person2 instanceof Person); // true
console.log(person1 instanceof Person); // false
This is because this object have a different nature even if they looks similar.
Answered By - Drag13
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.