0
votes

short: Having a method that returns a http call (get, put, whatever), determine the type of the items returned, using typescript types?

On TypeScrpt level, a promise is a generic type. It carries on the type of the message you expect, e.g. IPromise<T>. This way you can define that a method returns a promise of type Promise<number[]> which basically returns a promise that resolves with a list of numbers. Thanks to this, you make typescript even more powerful.

You can do the same with Observables (RxJS). Simple, we've got Observable<T> (just take a look at Observable.d.ts in npm:rxjs). Each item you expect in this stream is of type T (this is the subscribe callback parameter - has to be - TypeScript checks this for you).

Angular

Going back to Angular, the HTTP module wraps Observables. It doesn't return values immediately, but emits http calls with HTTP-related stuff (status, status text, url, etc), not just the value. In http's .d.ts, http.get, put, post, etc return Observable<Response>, where Response is the Angular built-in wrapper for HTTP call. But I see I lose the possibility to predefine the type of what a HTTP is supposed to return.

question is: is there a possibility in angular http calls to predefine what type is the http-call/observable return? Something like Observable<User> where User is just my application interface.

2
Why don't you use the framework as it is, and type it after your calls ? For instance, I type it in my services, with classes I created in the frontenduser4676340
@trichetriche not interested in subjective opinions. If you haven't used typed promises or typed observables before angular 2+ then you're not aware of what you're missing.ducin
Take a look here : github.com/maxime1992/angular-ngrx-starter/blob/master/src/app/… I think you want something like thatmaxime1992
@Maxime exactlyducin

2 Answers

2
votes

I assume you are looking for something like this:

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/of';

get(id: number): Observable<User> {
    const url = `${this.baseUrl}/${id}`;

    return this.http
               .get(url)
               .do((response: Response) => {
                 if (!response) {
                   return Observable.of(null);
                 }
               })
               .map((response: Response) => {
                   return <User>response.json();
               })
               .catch(error => {
                 return Observable.of(null);
               });
}
0
votes

Maybe this will help someone...

@Injectable()
export class UsersModel {
  getItem(id: number): Observable<User> {
    return this.http.get(`${API_URL}/users/${id}`, {
      headers: this.getHeaders()
    });
  }
}

In above code the error thrown is that Observable<Response> is in conflict with Observable<User>, distinct data types. The solution is just to include the observable.map((res) => res.json()) into the DAO method like here:

@Injectable()
export class UsersModel {
  getItem(id: number): Observable<User> {
    return this.http.get(`${API_URL}/users/${id}`, {
      headers: this.getHeaders()
    })
    .map((res) => res.json());
  }
}

Now there's no conflict, since res.json (of class Response) returns any. And this open the possibility for us to make getItem method return certain type of ours: getItem(id: number): Observable<User>. And I've got what I need - outside the DAO - in a component, for instance, I do:

this.UsersModel.getItem().subscribe(u => {
  u // u is of User already, yay!
})