Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular casting HttpClient response - class or interface

Tags:

I saw two methods to convert a response to our custom data model.

Interface

export interface User {
  id: number;
  name: string;
  more_complex_object: // so I am not sure how do this in right way. pass here another interface 
  //or just a object like {id: '', name: ''}. I show how to do this in class way...
}

And in service:

return this.http.get<User>...

And its fine, no need to do something more.

Class

export interface Deserializable {
  deserialize(input: any): this;
}

export class ComplexModel implements Deserializable {
  field1: string;
  field2: number;
  field3: number;

  deserialize(input: any): this {
    Object.assign(this, input);
    return this;
  }
}

export class User implements Deserializable {
 id: number;
 name: string;
 complex: ComplexModel;

 deserialize(input: any): this {
   Object.assign(this, input);
   this.complex = new ComplexModel().deserialize(input.complex));
   return this;
 }
}

And in service

return this.http.get('/users/id/').pipe(
  map(user => new User().deserialize(user))
);

As we can see in class method we must manually creating a object. Its fine with object like above, but when we have more complex object, or array of object we must do something like this:

return this.http.get('/users').pipe(
  map(users => {
    if (users instanceof Array) { // <- to avoid 'object has no method map' error
      return users.map(user => {
        return new User().deserialize(user);
      });
    }
  })
);

In class way we have much more complex code. And finally, the questions:

Any idea how do it as best as possible? Which methods is the best for you and why?

Interface-way looks more beautiful, but we don't have 'a real object' so we can't use class-methods, etc, right?

In class-way we get a real object, but is it so much needed?

like image 972
peryztor Avatar asked Jun 05 '18 06:06

peryztor


1 Answers

There is an explanation for this in the book: "Angular Up and Running" by Shyam Seshadri. I am quoting directly from the book Ch9 Making HTTP Calls in Angular p.178:

"One important thing to note is that the HttpClient can give you type-assurance across your code. We leverage this feature in the getStocks() and the toggleFavor ite() methods. One effect of this is that we need to change our stock.ts from a TypeScript class to a TypeScript interface. Why is this? While we don’t need to, Angular does a simple typecast of the response body into the type we have defined. But TypeScript (and ECMAScript underneath it) has no nice and easy way to convert a simple plain-old JavaScript object into a prototypical JavaScript/TypeScript class object. This means that while our response from StockService will have all the properties of the class Stock, it would not have the functions (in particular, isPositiveChange()) available. We could write a converter, but it is only worth it in very specific cases. It is easier to simply leverage TypeScript for type safety and work with other ways of encapsulation (either at a component level, or maybe as an Angular service)."

Please refer to the book for more explanation

like image 198
Ali Sawahreh Avatar answered Oct 02 '22 11:10

Ali Sawahreh