Cast TypeScript (ERROR TypeError)

0

The problem is as follows, through a service ( ModeloService ), I get an array of Modelo , where Modelo is a class, I happen to be unable to access the methods of this class, since cast in the service is not being done correctly, instead of cast being done to array Modelo , only one array of a normal javascript object, however, typed with Modelo . >

% injected% is http .

Follow the code with the classes mentioned:

I have the following class Angular2 , which represents a template (domain):

export class Modelo{
  id: number;
  type: string;
  size: number;

  constructor() {

  }

  public allowSize(): boolean {
    return this.type != null && (this.type.toLowerCase() == 'size');
  }

}

And the following service:

@Injectable()
export class ModeloService {

  constructor(private http: Http) {
  }

  getAll(): Observable<Modelo[]> {
    return this.http.get(myEnvironment.MODELO_SERVICE_PATH)
      .map(res => <Modelo[]> res.json());
  }

}

When trying to use this TypeScript method, I get the following error: allowSize()

modeloService.getAll()
  .subscribe(array=> array.forEach(modelo => console.log(modelo.allowSize())),
    error => console.log(error));

When I start ERROR TypeError: modelo.allowSize is not a function in the console, I do not get a modelo object, I only get a normal javascript object with key and values:

{id: 1;   type: 'size';   size: '10'}

The way I found to solve the problem was to create the object, as follows:

getAll(): Observable<Modelo[]> {
  return this.http.get(myEnvironment.MODELO_SERVICE_PATH)
    .map(res => {

      return (<Modelo[]> res.json()).map(modelo => {
        let modeloToReturn = new Modelo();
        modeloToReturn.id = modelo.id;
        modeloToReturn.type= modelo.type;
        modeloToReturn.size = modelo.size;

        return modeloToReturn;
      })

    });
}

Resolve, but it causes another problem that I have to keep evolving this service whenever I evolve my model, is not there a way to do this cast automatically?

    
asked by anonymous 12.01.2018 / 19:25

2 answers

0

I decided to solve the problem by instantiating a Model object, taking advantage of object orientation.

The way I put it in the post:

modelo.service.ts

getAll(): Observable<Modelo[]> {
  return this.http.get(myEnvironment.MODELO_SERVICE_PATH)
    .map(res => {

      return (<Modelo[]> res.json()).map(modelo => {
        let modeloToReturn = new Modelo();
        modeloToReturn.id = modelo.id;
        modeloToReturn.type= modelo.type;
        modeloToReturn.size = modelo.size;

        return modeloToReturn;
      })

    });
}
    
17.01.2018 / 18:03
1

You can not simply cast a cast from a JavaScript result of an Ajax request to a JavaScript / TypeScript class instance. There are several techniques to do this and generally involve copying data. Unless you create an instance of the class (as you did it yourself), you will not have any method or property. It will remain as a simple JavaScript object.

My suggestion is that you make a cast for a interface . An interface is purely a compile-time framework, meaning it has zero runtime impact on JavaScript. You can do something like this:

interface Modelo {
  id: number;
  type: string;
  size: number;
}

Using the above interface, it is necessary to move the logic of the allowSize() method to whoever has the reference of that array.

For example, you might have the following code in a component, say modelo.component.ts

private modelos: Modelo[];

ngOnInit() {
    this.modelos = this.service.getAll();
}

get allowSize(index: number): boolean {
    return this.modelos[index].type != null &&
           this.modelos[index].type.toLowerCase() === 'size';
}

Then in your template modelo.component.html

<div *ngFor="let modelo of modelos; let i = index">
    <div *ngIf="allowSize(i)">Allow Size</div>
</div>
    
15.01.2018 / 17:12