0

Lets suppose we have a rest api at this url /api/stuffs/ where we can get a list of Stuff.

here is the code to http get the list of Stuff:

getStuffs(): Observable<Stuff[]> {
    return this.http.get(this.url)
        .map(this.extractStuffs)
        .catch(this.handleError);
}

private extractStuffs(res: Response) {

    let stuffs = res.json() as Stuff[];

    return stuffs || new Array<Stuff>();
}

everything works fine with this code, except the fact that the stuffs array in the extractStuffs function is not an array of Stuff but and array of Object instead, even if the signature of the function is Observable<Stuff[]> and the result from the api is casted to Stuff[]. What's weird is that typescript compiler is not throwing any error (even if result type is different from signature), witch is totally normal if we take a look at the generated JS file :

StuffService.prototype.extractStuffs = function (res) {
    var stuffs = res.json();
    return stuffs || new Array();
};

So obviously casting the result into Stuff[] is not even considered by the compiler.

Is there any way to cast it properly without doing it manually ?

Thanks.

dafriskymonkey
  • 2,189
  • 6
  • 25
  • 48

1 Answers1

0

Every time I am in a similar situation I do casting through a loop (which I guess you define manually).

This is an example with Customers instead of Stuffs

getCustomers(code: string) {
        let url = environment.baseServicesUrl + 'customer';
        let jsonParam = {code: code};
        return this.http.post(url, jsonParam, this.getOptions())
                    .map(this.extractData)
                    .map((customerJsons) => {
                        let customers = new Array<Customer>();
                        customerJsons.forEach((customerJson) => {
                            customers.push(<Customer>customerJson);
                        })
                        return customers
                    })
                    .catch(this.handleError);
    }

The casting type Customer is an interface.

Here is the code of Customer.interface.ts

import {Relationship} from './relationship.interface';

export interface Customer {
    customerId: string;
    name: string;
    lastName: string;
    code: string;
    relationships: Array<Relationship>;
}

Here is the code for Relationship.interface.ts

export interface Relationship {
    id: string;
    type: string;
}
Picci
  • 16,775
  • 13
  • 70
  • 113
  • omitted to say that single object casting is not working either, the `stuffJson` still returns an `Object` instead of `Stuff`. here is the generated js => `jsonStuffs.forEach(function (jsonStuff) { return stuffs.push(jsonStuff); });` could something be missing in my compiler ??? – dafriskymonkey Oct 19 '16 at 18:08
  • Stuff needs to be an interface (not a class) for casting to work, I guess. Is this the case with you? – Picci Oct 19 '16 at 18:12
  • its a class indeed. ill retry with an interface. – dafriskymonkey Oct 19 '16 at 18:14
  • the interface didnt change much – dafriskymonkey Oct 19 '16 at 18:26
  • I have edited my answer with the complete code, including the interface. I hope this helps – Picci Oct 19 '16 at 18:35
  • 1
    Maybe it is worth also adding that interfaces in Typescript are not compiled into runtime code. They are usefull to enforce typing at development time. See (http://stackoverflow.com/questions/22875636/how-do-i-cast-a-json-object-to-a-typescript-class) – Picci Oct 19 '16 at 18:41
  • yeah, thats the problem. no casting in typescript at runtime :( – dafriskymonkey Oct 19 '16 at 19:51