Typescript returning boolean after promise resolved
Asked Answered
F

2

22

I'm trying to return a boolean after a promise resolves but typescript gives an error saying

A 'get' accessor must return a value.

my code looks like.

get tokenValid(): boolean {
    // Check if current time is past access token's expiration
    this.storage.get('expires_at').then((expiresAt) => {
      return Date.now() < expiresAt;
    }).catch((err) => { return false });
}

This code is for Ionic 3 Application and the storage is Ionic Storage instance.

Fasces answered 13/8, 2017 at 18:36 Comment(12)
You can't do this... You can return a Promise<boolean> by just returning this.storage.get... though.Disquieting
@Fasces I've not usually seen asynchronous code inside of a get, rather the async process sets a property, that the get retrieves...Ketron
And you probably shouldn't use a getter for a thing that has side effects.Ceiba
@bergi It does not look to me like the code inside tokenValid is causing side effects. Can you provide more details.Weakfish
@ShaunLuttin it queries the storage (which takes time) and can change at any timeCeiba
@Ceiba The vocabulary here is unclear to me. I was under the impression that side effects refer to causing mutations outside the function's body. What you're referring to seems more like a violation of referential transparency, unless a query to the storage is causing the storage to change.Weakfish
@ShaunLuttin Yes, that's a more accurate description. I used "side effect" because a) time is often considered as one b) we indeed don't know what a query does (and "sending a request" could be an action that mutates all kinds of stuff, at least on the lower levels).Ceiba
@Ceiba Thank you for the additional details. I appreciate it.Weakfish
@Ceiba Is there way to use this code, not as a getter and making it function with this async behavior and return boolean?Fasces
@Fasces No, when it's asynchronous it has to return a promise for the boolean. To make it a method, just omit the get.Ceiba
@Ceiba Can I use async/await and make this call synchronous?Fasces
@Fasces No, it's impossible to make it synchronous. Using async/await syntax only is sugar for then calls - it's still asynchronous and returns a promise.Ceiba
W
31

You can return a Promise that resolves to a boolean like this:

get tokenValid(): Promise<boolean> {
  // |
  // |----- Note this additional return statement. 
  // v
  return this.storage.get('expires_at')
    .then((expiresAt) => {
      return Date.now() < expiresAt;
    })
    .catch((err) => {
      return false;
    });
}

The code in your question only has two return statements: one inside the Promise's then handler and one inside its catch handler. We added a third return statement inside the tokenValid() accessor, because the accessor needs to return something too.

Here is a working example in the TypeScript playground:

class StorageManager { 

  // stub out storage for the demo
  private storage = {
    get: (prop: string): Promise<any> => { 
      return Promise.resolve(Date.now() + 86400000);
    }
  };

  get tokenValid(): Promise<boolean> {
    return this.storage.get('expires_at')
      .then((expiresAt) => {
        return Date.now() < expiresAt;
      })
      .catch((err) => {
        return false;
      });
  }
}

const manager = new StorageManager();
manager.tokenValid.then((result) => { 
  window.alert(result); // true
});
Weakfish answered 13/8, 2017 at 22:36 Comment(2)
@Fasces I'm afraid I don't know what additional information to provide in this answer.Weakfish
This won't pass a tslint test considering Promise<boolean> is not the only possible return type. Better to use Promise<any>Spatiotemporal
S
11

Your function should be:

get tokenValid(): Promise<Boolean> {
    return new Promise((resolve, reject) => {
      this.storage.get('expires_at')
        .then((expiresAt) => {
          resolve(Date.now() < expiresAt);
        })
        .catch((err) => {
          reject(false);
      });
 });
}
Scandic answered 14/8, 2017 at 10:43 Comment(4)
Hello, if I change the code reject(false); to reject(err), can I get the false value?Bertrando
No, the parameter of reject function must be the same as the return type of your function.Scandic
Okay, if we don't use resolve or reject, is that okay? I mean we just return a bool value and not pass resolve or reject. If so, what is the propose of resolve?Bertrando
As you can see i return new Promise class, so i need to call resolve or reject. If you want to return only value true or false, you just write: this.storage.get('expires_at') .then((expiresAt) => { return Date.now() < expiresAt; }) .catch((err) => { return false; });Scandic

© 2022 - 2024 — McMap. All rights reserved.