Search code examples
javascripttypescriptcompiler-errorspromisetsc

TypeScript error TS2345 when rejecting a Promise with an error


I have a TypeScript error message whose error I do not understand. The error message is:

error TS2345: Argument of type '(error: Error) => void | Promise' is not assignable to parameter of type '(reason: any) => IdentityKeyPair | PromiseLike'. Type 'void | Promise' is not assignable to type 'IdentityKeyPair | PromiseLike'.

My code was working fine but TypeScript got mad at me when I changed this block:

.catch((error) => {
  let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
  return this.store.save_identity(identity);
})

into this:

.catch((error) => {
  if (error instanceof RecordNotFoundError) {
    let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
    return this.store.save_identity(identity);
  } else {
    return reject(error);
  }
})

Here is the complete code which was working:

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
      .catch((error) => {
        let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
        return this.store.save_identity(identity);
      })
      .then((identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
      })
      .then((lastResortPreKey: Proteus.keys.PreKey) => {
        return resolve(lastResortPreKey);
      })
      .catch(reject);
  });
}

And here is the code which does not compile anymore:

public init(): Promise<Array<Proteus.keys.PreKey>> {
  return new Promise((resolve, reject) => {
    this.store.load_identity()
      .catch((error) => {
        if (error instanceof RecordNotFoundError) {
          let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
          return this.store.save_identity(identity);
        } else {
          return reject(error);
        }
      })
      .then((identity: Proteus.keys.IdentityKeyPair) => {
        this.identity = identity;
        return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
      })
      .then((lastResortPreKey: Proteus.keys.PreKey) => {
        return resolve(lastResortPreKey);
      })
      .catch(reject);
  });
}

Does anyone sees why the TypeScript compiler refuses my return reject(error); statement with error code TS2345?

Screenshot:

error TS2345

I am using TypeScript 2.1.4.


Solution

  • Try out below. When you are in a then or catch block you can return a Promise or a value which gets wrapped into a Promise. You are manually working with a Promise yourself so you can just call the resolve and reject handlers without needing to return anything. Returning reject(error) would try to take that returned value, wrap it in a Promise and then try to pass to the next then block which is why you were getting the error you did. Think of it this way: returning something in a handler means continue down the chain with this new value. In your case I think you just want to stop the chaining and have the Promise you are creating resolve or reject under certain conditions.

    public init(): Promise<Array<Proteus.keys.PreKey>> {
      return new Promise((resolve, reject) => {
        this.store.load_identity()
          .catch((error) => {
            if (error instanceof RecordNotFoundError) {
              let identity: Proteus.keys.IdentityKeyPair = Proteus.keys.IdentityKeyPair.new();
              return this.store.save_identity(identity);
            } else {
              throw error;
            }
          })
          .then((identity: Proteus.keys.IdentityKeyPair) => {
            this.identity = identity;
            return this.store.load_prekey(Proteus.keys.PreKey.MAX_PREKEY_ID);
          })
          .then((lastResortPreKey: Proteus.keys.PreKey) => {
            resolve(lastResortPreKey);
          })
          .catch((error) => {
            reject(error);
          });
      });
    }