Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript type Function returning a Promise

I am building an ionic app that is pulling in an rss feed from iTunes. I am able to get the rss feed and display the entries on my app.

I am getting this error, and would like to understand how to properly set up the variable.

export class MyPage {
    episodes: any;

    ...


    getRssFeed() {
        this.rssProvider.getFeed(this.rssUrl)
            .then(data => {
                console.log(data);
                this.episodes = data.items;
        });
    }
}

rssProvider.ts

...

getFeed(rssUrl: string) {
    try {
        return new Promise(resolve => {
            this.http.get(`${this.baseUrl}?rss_url=${rssUrl}&api_key=${this.apiKey}&count=${this.count}`).subscribe(data => {
            resolve(data);
        }, error => {
           console.error(error);
        });
      });
    } catch (error) {
        console.error('Something really bad happened trying to get rss feed.');
        console.error(error);
    }
}

I am using WebStorm for my IDE if that is of any significance.

This is the error I am getting:

Typescript Error:
Property 'items' does not exist on type '{}'.

Which ok, items is coming back, so ionic doesn't know what it is. Is there a proper way to declare the variable so I don't get the red error hinting?

Thank you for any suggestions!

like image 867
Damon Avatar asked Jun 12 '18 22:06

Damon


People also ask

How do I return a promise from a function?

Promise resolve() method: If the value is a promise then promise is returned. If the value has a “then” attached to the promise, then the returned promise will follow that “then” to till the final state. The promise fulfilled with its value will be returned.

How do you define a type of promise in TypeScript?

In TypeScript, promise type takes an inner function, which further accepts resolve and rejects as parameters. Promise accepts a callback function as parameters, and in turn, the callback function accepts two other parameters, resolve and reject. If the condition is true, then resolve is returned; else, returns reject.

Can a normal function return a promise?

As a side note, we can return a promise from any function. It doesn't have to be asynchronous. That being said, promises are normally returned in cases where the function they return from is asynchronous. For example, an API that has methods for saving data to a server would be a great candidate to return a promise!

How do you return a promise in typescript?

Promise accepts a callback function as parameters, and in turn, the callback function accepts two other parameters, resolve and reject. If the condition is true, then resolve is returned; else, returns reject. Basically, the return type of Promise type is defined immediately after the keyword Promise. How does TypeScript Promise type work?

What happens if you don't set the return type in typescript?

If you don't explicitly set the return type of the function, TypeScript will infer it. If your function returns a Promise that may contain different values, use a union to specify the function's return type. The function above returns a Promise that contains a string or a null value.

How to unwrap a promise type from a function's return type?

If the return type of the function is not set, TypeScript will infer it. You can set the return type of a function right after its parameter list. If you need to unwrap the type of the Promise from a function's return type, use the Awaited utility type. The Awaited utility type recursively unwraps a promise and returns its type.

What is the difference between resolve and reject in typescript?

If the function’s response is a success, then it will return ‘resolve’; if the response from the function is not successful, it will return ‘reject’. 3. States available in promise of Typescript: Promise support several states.


2 Answers

Promise Type

You first need to define what will be the type returned by your API:

type ResultType = {
  items: string[]
}

Then, tell TypeScript that getFeed returns a Promise of ResultType:

getFeed(rssUrl: string): Promise<ResultType>

Or specify the generic type after the Promise constructor:

return new Promise<ResultType>(resolve => {})

Error Handling

Finally, instead of handling error directly in getFeed use the reject from Promise to do error handling directly in the Promise.

getFeed(rssUrl: string) {
  return new Promise<ResultType>((resolve, reject) => {
    this.http.get(URL_ENDPOINT).subscribe(
      data => {
        resolve(data)
      },
      error => {
        // Transform your error here if needed
        reject(error)
      }
    )
  })
}

Usage

Using Promise

getFeed()
  .then(feed => {
    console.log(feed)
  })
  .catch(error => {
    console.error(error)
  })

Using async/await:

try {
  const feed = await getFeed()
  console.log(feed)
} catch (error) {
  console.error(error)
}
like image 146
kube Avatar answered Oct 18 '22 01:10

kube


When you do return Promise, the return type defaults to {}, so TypeScript thinks that data is actually {}. Promise takes a generic argument that is the type you get from .then, so you could do something like Promise<{ items: any }>. You could also create interface RssResponse { items: any }, and probably use a better type than just any for items.

return new Promise<RssResponse>(resolve => {

However, you don't need to wrap this code in a promise constructor at all. Observables have a toPromise method, so you can simplify this to:

getFeed(rssUrl: string) {
    return this.http.get(...).toPromise();

...which should function identically.

Moreover, you can just subscribe to the result in your Page:

getFeed(rssUrl: string): Observable<RssResponse> {
  return this.http.get(...);


// In MyPage
getRssFeed() {
    this.rssProvider.getFeed(this.rssUrl).subscribe(data => {
        this.episodes = data.items;
    });
}
like image 43
Explosion Pills Avatar answered Oct 18 '22 00:10

Explosion Pills