【问题标题】:Same return type like callback与回调相同的返回类型
【发布时间】:2021-09-09 15:14:13
【问题描述】:

我创建了一个通用的错误处理程序包装函数,它在出现错误时处理错误并返回回调的结果。我的问题是打字稿不允许我返回承诺,因为

TS2322: Type 'Promise<unknown>' is not assignable to type 'R'.
   'R' could be instantiated with an arbitrary type which could be unrelated to 'Promise<unknown>'

这是我的职责

export function withErrorHandler<R>(action: string, callback: () => R): R {
  function isPromise<X>(promise: Promise<X> | unknown): promise is Promise<X> {
    return promise instanceof Promise;
  }
  try {
    const result = callback();

    if (isPromise(result)) {
      return result.catch(error => {
        handleError(error, action);
        throw error;
      });
    }

    return result;
  } catch (error) {
    handleError(error, action);
    throw error;
  }
}

谁知道如何编写泛型来推断返回类型并允许它在回调返回 Promise 时返回 Promise 或返回非 Promise? 谢谢

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    编译器无法验证result.catch(...) 返回的Promise 是否与result 完全相同。例如,编译器都知道,result 是具有额外属性的 Promise,而 result.catch 肯定是 Promise,但它可能没有这些相同的额外属性。这实际上可能发生并导致运行时错误:

    const promiseWithCheese = Object.assign(Promise.resolve(10), { cheese: "cheddar" });
    const weh = withErrorHandler("x", () => promiseWithCheese);
    try {
        weh.cheese.toUpperCase(); //accepted at compile time, but
    } catch (e) {
        console.log(e); // ? weh.cheese is undefined
    }
    

    我认为这不太可能,您也不必担心。如果是这样,那么对你来说最简单的事情就是assert 使result.catch()result 具有相同的类型:

    if (isPromise(result)) {
        return result.catch(error => {
            // handleError(error, action);
            throw error;
        }) as (typeof result);
    }
    

    现在编译器不会警告RPromise&lt;unknown&gt; 之间的不匹配,因为您已经告诉它result.catch() 返回类似R &amp; Promise&lt;unknown&gt; 的内容。

    Playground link to code

    【讨论】:

    • 太棒了,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2018-02-23
    • 2018-12-24
    相关资源
    最近更新 更多