TypeScript 中,Promise 的 reject 无法使用类型推导吗?

遇到一个 TypeScript 中有关 Promise 的类型推导问题:

以下代码中,resolve 会有明确的类型限制,但 reject 却没有,想知道如何才能做到?

type P1 = Promise<number>;

const p1: P1 = new Promise((resolve, reject) => {
  // Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?ts(2794)
  resolve();
  resolve(1);
  // Argument of type 'string' is not assignable to parameter of type 'number | PromiseLike<number>'.ts(2345)
  resolve("str");

  reject();
  reject(123);
  reject("str");
});

image.png

查看 Promise 的类型声明

image.png

只有一个泛型参数,貌似不支持。
找到了这篇文章,文章的结论是:无法定义,也无需定义。

Typescript 中 Promise reject 的类型该如何定义?

希望 reject 也能有明确的类型推导,但貌似原理上不可行。

那么,在处理 catch 的时候,编辑器报出来的 any,应该怎么处理比较优雅呢?

p1.catch((err: any) => {})

除了在这里直接声明,还有什么最佳实践吗?

阅读 1.4k
2 个回答

这个是设计如此吧,毕竟你确实可能不知道会 catch 到什么错误

不过好像可以包装一个确定错误类型的 PromiseE

type Nullable<T> = T | null | undefined
type MaybePromiseLike<T> = T | PromiseLike<T>

class PromiseE<T, E = any> extends Promise<T> {
  constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: E) => void) => void) {
    super(executor)
  }
  catch<R = never>(onrejected?: ((reason: E) => R | PromiseLike<R>) | undefined | null): Promise<T | R> {
    return super.catch(onrejected)
  }
}

const p = new PromiseE<number, string>((res, rej) => {
  res(1)
  // @ts-expect-error
  rej(2)
  rej('3')
})

p.catch(err => {
  err // err: string
})

我也提供一个解决方案吧

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 1000)
});

class ErrorModel<T = void>{
  detail?: T;
  timeTemp?: number;
  constructor(error: Partial<ErrorModel>) {
    Object.assign(
      this,
      error,
      {
        timeTemp: Date.now()
      })
  }

  log() {
    console.log('error', JSON.stringify(this.detail || {}));
  }
}

export class CallModel<T = void, E = void>{
  data?: T;
  error?: ErrorModel<E>;
}

function Callback<D, E>(promise: Promise<D>) {
  return promise
    .then<CallModel<D>>((data) => ({ data }))
    .catch<CallModel<D, E>>((error) => ({ error })) as Promise<CallModel<D, E>>;
}

Callback<number, string>(p1 as Promise<number>).then(({ data, error }) => {
  if(error){
    error?.log();
    return;
  }
  //  resulut
  console.log(data!);
})
推荐问题
logo
Microsoft
子站问答
访问
宣传栏