首页 > 解决方案 > 与回调相同的返回类型

问题描述

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

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?thx <3

标签: typescripttypescript-generics

解决方案


编译器无法验证result.catch(...)返回的Promise类型与result. 例如,编译器都知道,resultis aPromise具有额外的属性,虽然result.catch肯定是 a 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
}

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

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

现在编译器不会警告 and 之间的不匹配RPromise<unknown>因为你已经告诉它result.catch()返回类似R & Promise<unknown>.

Playground 代码链接


推荐阅读