打字稿承诺拒绝类型

Kou*_*sha 12 javascript promise typescript

如何设置拒绝承诺的类型?让我说我做:

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

假设我想拒绝一个数字.但我不能设置类型; 我可以把我想要的任何东西传给reject这里.

此外,在使用此承诺时,如果我错误地使用拒绝响应类型,我想要编译错误.

Est*_*ask 16

正如在解释这个问题,Promise没有不同类型的满足,拒绝承诺.reject 接受any不影响promise类型的参数.

目前Promise无法打字任何更好.这是因为承诺可以throw通过内部拒绝thencatch(这是拒绝现有承诺的一种可取方式),而这不能通过键入系统来处理; 另外,TypeScript也没有特殊于异常的类型never.


Mik*_*sin 7

异常类型为any,因为我们无法在设计时保证异常类型的正确性,而且TypeScript和JavaScript都不提供在运行时保护异常类型的能力。 最好的选择是使用类型防护在代码中提供设计时和运行时检查。

来源


小智 7

因为在某些情况下无法设置错误类型,例如 Promise 或异常抛出,我们可以以类似 rust 的方式处理错误:

// 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;
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 我建议不要使用这种模式。问题是您现在有两种错误处理方法,检查结果的错误类型和使用“.catch”。当然,您可以假设您的整个代码库仅使用错误结果,但我向您保证,在任何大型项目中,这种假设都会让您付出代价。 (3认同)
  • 我知道这一点,但这并没有改变我所说的话。假设是导致问题的原因。另外,虽然 Result 可能是真正的 sum 类型,但 Promise 不是 monad,所以你确实不在 FP 领域。我已经在这条路上走过太多次了,而且不仅仅是使用 TypeScript。说实话,我应该有点宽容,因为直到有人为 TypeScript 中的异步编程创建真正的单子双函子之前,每次看到“Promise”这个词我都会感到畏缩。如果上帝给我多一点时间,我就会成为那个人。 (3认同)
  • 嘿@LodewijkBogaards,我很想知道您对我构建的这个异步结果库的想法:https://github.com/GabrielCTroia/ts-async-results。我认为你对上述模式处理错误的冲突方式提出了一个很好的论点,因此为什么我选择抽象出新实体背后的“异步”组件 - AsyncResult 它恰好在下面使用了一个承诺,但外界需要不知道这个。 (2认同)
  • @GabrielC.Troia 哈哈!我最近找到了你的库,并将其展示给我们的前端技术负责人,并告诉他:应该这样做:) 如果你碰巧在找工作:欢迎你随时在 StackState 工作! (2认同)

mpe*_*pen 5

这是我尝试输入的内容:

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>;
}
Run Code Online (Sandbox Code Playgroud)

像平常一样使用它:

return new ErrPromise<T,ExecError>((resolve, reject) => { ... })
Run Code Online (Sandbox Code Playgroud)

您的 IDE 应选择以下类型reject

在此输入图像描述

在此输入图像描述