0

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.

4
  • 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 frontend Commented May 24, 2017 at 14:22
  • @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. Commented May 24, 2017 at 14:26
  • 1
    Take a look here : github.com/maxime1992/angular-ngrx-starter/blob/master/src/app/… I think you want something like that Commented May 24, 2017 at 14:26
  • @Maxime exactly Commented May 24, 2017 at 14:33

2 Answers 2

2

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);
               });
}
Sign up to request clarification or add additional context in comments.

2 Comments

seems like just a wrapper. But in order to be used as a DAO method, I'd just remove .catch (client component can handle that). Makes sense, thanks
yes, it is basically a wrapper and you could genericize it. you could remove the catch, but it would provide a way to handle the errors consistently.
0

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!
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.