admin管理员组

文章数量:1134570

How do I set the type of the rejection of my promise? Let's say I do:

const start = (): Promise<string> => {
   return new Promise((resolve, reject) => {
      if (someCondition) {
         resolve('correct!');
      } else {
         reject(-1);
      }
   });
}

Let's say I want to reject with a number. But I cannot set the type; I can pass whatever I want to the reject here.

Moreover, when using this promise, I want to have compiling error if I use the rejection response type incorrectly.

How do I set the type of the rejection of my promise? Let's say I do:

const start = (): Promise<string> => {
   return new Promise((resolve, reject) => {
      if (someCondition) {
         resolve('correct!');
      } else {
         reject(-1);
      }
   });
}

Let's say I want to reject with a number. But I cannot set the type; I can pass whatever I want to the reject here.

Moreover, when using this promise, I want to have compiling error if I use the rejection response type incorrectly.

Share Improve this question asked Apr 27, 2018 at 22:38 KoushaKousha 36.1k58 gold badges185 silver badges313 bronze badges 1
  • 2 This issue may be of interest. – CRice Commented Apr 27, 2018 at 22:58
Add a comment  | 

9 Answers 9

Reset to default 124

As explained in this issue, Promise doesn't have different types for fulfilled and rejected promises. reject accepts any argument that doesn't affect type of a promise.

Currently Promise cannot be typed any better. This results from the fact that a promise can be rejected by throwing inside then or catch (this is a preferable way to reject existing promise), and this cannot be handled by typing system; also, TypeScript also doesn't have exception-specific types except never.

Cause there is no way to set error type in some cases like Promise, or exception throws, we can work with errors in rust-like style:

// Result<T, E> is the type used for returning and propagating errors.
// It is an sum type with the variants,
// Ok<T>, representing success and containing a value, and 
// Err<E>, representing error and containing an error value.
export type Ok<T> = { _tag: "Ok"; ok: T };
export type Err<E> = { _tag: "Err"; err: E };
export type Result<T, E> = Ok<T> | Err<E>;
export const Result = Object.freeze({
  Ok: <T, E>(ok: T): Result<T, E> => ({ _tag: "Ok", ok }),
  Err: <T, E>(err: E): Result<T, E> => ({ _tag: "Err", err }),
});

const start = (): Promise<Result<string, number>> => {
  return new Promise((resolve) => {
    resolve(someCondition ? Result.Ok("correct!") : Result.Err(-1));
  });
};

start().then((r) => {
  switch (r._tag) {
    case "Ok": {
      console.log(`Ok { ${r.ok} }`);
      break;
    }
    case "Err": {
      console.log(`Err { ${r.err} }`);
      break;
    }
  }
});

The exception is typed any because we cannot guarantee the correct type of the exception at design time, and neither TypeScript nor JavaScript provide the ability to guard exception types at run time. Your best option is to use type guards to provide both a design-time and run-time check in your code.

source

Here's my attempt at typing it:

export class ErrPromise<TSuccess, TError> extends Promise<TSuccess> {
    constructor(executor: (resolve: (value: TSuccess | PromiseLike<TSuccess>) => void, reject: (reason: TError) => void) => void) {
        super(executor);
        // Object.setPrototypeOf(this, new.target.prototype);  // restore prototype chain
    }
}

export interface ErrPromise<TSuccess, TError = unknown> {
    then<TResult1 = TSuccess, TResult2 = never>(onfulfilled?: ((value: TSuccess) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: TError) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;

    catch<TResult = never>(onrejected?: ((reason: TError) => TResult | PromiseLike<TResult>) | undefined | null): Promise<TSuccess | TResult>;
}

Use it like normal:

return new ErrPromise<T,ExecError>((resolve, reject) => { ... })

Your IDE should pick up the type of reject:

What @EstusFlask mentioned in his answer is correct.

But I want go one step near to an artificial solution to simulate what we want with TypeScript capabilities.

 

Sometimes I use this pattern in my codes

本文标签: javascriptTypescript Promise rejection typeStack Overflow