Mike Spencer Mike Spencer - 3 months ago 52
TypeScript Question

RxJS observables and generic types for Angular2(Typescript) http wrapper

Today I encountered the following problem while trying to implement an abstract http service. This service should be base to extend for all other http services.

The implementation is following so far, skipping other methods for ilustration:

@Injectable()
export abstract class HttpWrapper<T> {

private options: RequestOptions;

constructor(private http: Http, private endpointUrl: string) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.options = new RequestOptions({ headers: headers });
}

public getAll(): Observable<T[]>{
return this.http.get(this.endpointUrl, this.options)
.map(this.extractAll)
.catch(this.handleError);
}

abstract handleError(error: any):Observable<Response>;

abstract extractOne(res: Response):T;

abstract extractAll(res: Response):T[];
}


Now if i want to use the abstract HttpWrapper i do the following:

@Injectable()
export class BlastReportService extends HttpWrapper<Item> {

constructor(http: Http) {
super(http,'/api/items');
}


handleError(error: any):Observable<Response>{
//Handling error
return Observable.throw(error);
}

extractAll(res: Response):Item[]{
let body = res.json();

let formatedBody = body.map((item: Item) => {
item = new Item(item);
return blastReport;
});

return formatedBody || [{}];
}
}


But doing this I get following compilation error:

Type 'Observable<Response>' is not assignable to type 'Observable<T[]>'.
Type 'Response' is not assignable to type 'T[]'.
Property 'find' is missing in type 'Response'.


I can't wrap my head around this because the method extractAll clearly returns Item[] and is used while mapping the results returned from the server.

I decided to implement this abstract HttpWrapper "to stay DRY". I'm not sure if it's the best way to do so.

Answer

It looks like the problem here is that handleError() returns an Observable<Reponse>, and therefore cannot be the return value of getAll() which expects an Observable<T[]>

Changing the return type of handleError to Observable<T[]> should fix the issue.

In HttpWrapper

abstract handleError(error: any):Observable<T[]>

In BlastReportService

handleError(error: any): Observable<T[]> {
  return Observable.throw(error)
}
Comments