首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在TypeScript中,为什么异步函数不能返回类型为T\ Promise<T>的联合?

在TypeScript中,为什么异步函数不能返回类型为T\ Promise<T>的联合?
EN

Stack Overflow用户
提问于 2019-08-28 15:42:30
回答 1查看 2.5K关注 0票数 5

我正在类型记录中构建一个API,有些控制器操作可以是同步的,而另一些则不能。

代码语言:javascript
复制
type ActionResult =IHttpActionResult | Promise<IHttpActionResult>;

然后,当我构建操作时,当它们变得基于承诺时,我就可以预先准备异步并完成它。

但是,type typescript抱怨说,“异步函数或方法的返回类型必须是全局允诺类型。”

为什么异步函数不能返回T | Promise<T>的联合

下面是一个例子:

代码语言:javascript
复制
type StringPromise = Promise<string>;

// These two work as you'd expect
async function getHello(): Promise<string> {
    return 'hello';
}

async function getGoodbye(): StringPromise {
    return 'goodbye';
}

type StringyThingy = string | Promise<string>;

// the next two work as you would expect them to
function getHoorah(): StringyThingy {
    return 'hoorah!';
}

function getWahoo(): StringyThingy {
  return new Promise(resolve => resolve('wahoo'));
}

// This one results in the error:
// "the return type of an async function or method must be the global Promise type."
async function getSadface(): StringyThingy {
  return ':(';
}    

下面是上面代码的一些示例输出:

代码语言:javascript
复制
getHello().then(console.log);
getGoodbye().then(console.log);
console.log(getHoorah());

// The library I'm using is probably using typeguards for this
// I'd imagine
const wahoo = getWahoo();
if (typeof(wahoo) === 'string') {
  console.log(wahoo);
} else {
  wahoo.then(console.log);
}
EN

回答 1

Stack Overflow用户

发布于 2019-08-28 15:44:35

async表示法是语法糖,用于:“此函数将始终返回承诺。”

即使你宣布它是这样:

代码语言:javascript
复制
const foo = async() => 3;

它基本上与以下内容相同(虽然更严格):

代码语言:javascript
复制
const foo = () => new Promise(resolve => resolve(3));

或作为:

代码语言:javascript
复制
const foo = () => Promise.resolve(3);

所有这些例子都将得到一个承诺。

主要的区别是,“普通”函数可以同时返回一个允诺和其他类型,但是一旦使用了async,它总是会返回一个承诺。

即使承诺立即解决,async函数也不可能不通过设计返回承诺。

你将不得不等待它/使用它。

这一点在mozilla关于异步关键字的JavaScript引用上也有说明。

异步函数声明定义了一个异步函数,它返回一个AsyncFunction对象。异步函数是通过事件循环异步操作的函数,它使用隐式承诺返回其结果。但是,使用异步函数的代码的语法和结构更像使用标准同步函数。

特别是返回类型:

这个承诺将用异步函数返回的值来解析,或者在异步函数中抛出一个未察觉的异常而被拒绝。

考虑到这一点,我建议将API async设为默认设置。如果您的某些操作是同步的,对于外部世界来说,这并不重要。在这种情况下,你可以马上解决这个承诺。不需要你的type StringyThingy = string | Promise<string>;

键入Promise<string>,让异步将包装处理成对您的承诺,或者在实际的异步用例中返回其他承诺。这样,您就不必检查承诺的情况,但是您将以相同的方式处理异步/同步分支。

如果您真的希望使用union类型(我真的不建议这样做),那么您必须放弃使用async关键字。

您可以定义返回任一类型的正常函数:

代码语言:javascript
复制
const foo = (x:number): Promise<number>|number => {
    if(x >=0) {
         return new Promise(resolve => resolve(x));
    } else {
         return x;
    }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57695992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档