0

I declare a model in ingredient.model.ts

export class Ingredient {
 constructor(private name: string, public amount: number) {}

 getName() { return this.name }
}

In ingredients.service.ts, if I get them in this way:

httpClient.get<Ingredient>(url).subscribe(
 (igredient) => {
   console.log(igredient.getName());
 });

It gives errors in console, such as "no method getName in property igredient".

Also, whenever I try to declare a property type Category[] it fails, but Array seems working fine.

Edit: I want to provide more info.

Given the Igredient model and the following JSON structure:

{
 name: "Apple",
 amount: "5",
 created_at: "date",
}

The Igredient constructor isn't even invoked, therefore the GET payload won't be parsed.

zangarmarsh
  • 319
  • 5
  • 18

2 Answers2

5

You'll need to use a property, not a method. The returned object is really a json object, and there is no such thing as "getName()" method (despite your effort to add a type information). Try something like this:

export interface Ingredient {
    strin: string,
    amount: number,
    created_at: string
}


httpClient.get<Ingredient>(url).subscribe(
     (igredient) => {
          console.log(igredient.amount);
});

EDIT: You need to provide a type information based on the expected json object. If the returned json object has attributes, strin, amount, and created_at, then you need to define a type that is compatible with the expected json object.

realharry
  • 1,555
  • 8
  • 12
  • So what's the use of a custom Ingredient class? PS: If I insert a debugger into the constructor, it is not even called! – zangarmarsh Nov 26 '17 at 18:27
  • 1
    `ingredient.name` does not throw an error because you defined a type `Ingredient`. – realharry Nov 26 '17 at 18:28
  • ok, thank you. I didn't know that. Look at the EDIT please, I'm still having issues. – zangarmarsh Nov 26 '17 at 18:41
  • @zangarmarsh I don't see any "name" filed in your expected json return object. Updated the answer. Note that you are not really "casting" or "constructing" an object. You are simply providing a type information to the compiler so that you can use expressions like `ingredient.amount` in your code. – realharry Nov 26 '17 at 18:54
  • Oh ok, I thought the object would have been parsed by the constructor. Thank you for the info! – zangarmarsh Nov 26 '17 at 19:10
1

In angular 5, You can do this:

export interface Deserializable<T> {
    deserialize(input: any): T;
  }

export class Ingredient implments Deserializable<Ingredient>{
constructor(private name: string, public amount: number) {}

deserialize(input: any): Project {
    Object.assign(this, input);
    // do nested thing here -pop arrays of nested objects and create them
    }
    return this;
  }

now in your service:

  httpClient.get<Ingredient>(url).pipe(map(elem=>this.foo(elem)))
 .subscribe((igredient) => {console.log(igredient.getName());
   });

foo(ingredient:Ingrdient){
 var i = new Ingridiant().desrialize(ingredient)
}

after the map you will have the Ingradient class, not the object.

Lior Alon
  • 163
  • 1
  • 6