TS: 基于 Promise 结果断言函数 return

TS: Assert function return based on Promise result

问题

给定一个返回 Promise,

的函数
const fetchSomething = async (): Promise<DocumentType | ServerErrorType> => {
  const data = await fetch(`/data`, {
    method: "get",
    headers: { "Content-Type": "application/json" },
  });
  try {
    const res = await data.json();
    return Promise.resolve(res);
  } catch (err) {
    return Promise.reject(err);
  }
};

这样称呼,

// TS evaluates both res and err as 'DocumentType | ServerErrorType'
fetchSomething()
  .then((res) => console.log(res))
  .catch((err) => console.log(err))

如何以一种方式断言和调用它,如果 Promise 解析,结果将被断言为 DocumentType,而如果它拒绝,则它断言结果为 ServerErrorType?

替代解决方案

简单快捷的解决方法,就是在调用函数的时候直接断言这个值,如下:

// TS evaluates res as 'DocumentType' and err as 'ServerErrorType'
fetchSomething()
  .then((res as DocumentType) => console.log(res))
  .catch((err as ServerErrorType) => console.log(err))

这样断言的问题是,我最终会在我调用它的任何地方断言该函数的结果。

我尝试了什么

我尝试以这种方式断言 fetchSomething 上的值:

try {
  const res = await data.json();
  return Promise.resolve(res as DocumentType);
} catch (err) {
  return Promise.reject(err as ServerErrorType);
}

但这似乎无助于 TS 评估正确的类型。

结论

是否有一种干净的方法可以根据 Promise 结果(已解决或已拒绝)直接在该函数内断言返回值?

Typescript 当前不支持 catch 变量的类型注释。参见 here.

顺便说一句,我确实推荐@T.J.Crowder

建议的更改

这个 promise 没有像你预期的那样起作用。不幸的是,Promises 不支持错误类型 - 从 Promise.catch 传递的值将 总是 键入为 anyPromise<T> 中的 T 仅将 引用到如果您等待承诺或使用 .then.[=16= 时您将收到的值]

简而言之,您的尝试是不可能的。您真正能做的就是将 T 设置为成功类型的类型,然后在捕获臂中允许类型推断。