我正在用打字稿构建API,一些控制器动作可以同步,而其他控制器则不能。我想这样指定响应类型:
type ActionResult =IHttpActionResult | Promise<IHttpActionResult>;
然后,当我在构建动作时,当它们成为基于诺言的动作时,我可以在异步之前添加并完成它。
但是,打字稿抱怨“异步函数或方法的返回类型必须是全局Promise类型。”
为什么异步函数不能返回T | Promise<T>
的并集?
这是一个例子:
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 ':(';
}
以下是上面代码的一些示例输出:
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);
}
答案 0 :(得分:3)
async
表示法是:
此功能将始终返回承诺。
即使您这样声明:
const foo = async() => 3;
与以下基本相同(尽管更为严格):
const foo = () => new Promise(resolve => resolve(3));
或作为:
const foo = () => Promise.resolve(3);
所有这些示例都将返回一个Promise。
主要区别在于,“常规”函数可以返回Promise和其他类型,但是一旦使用async
,它总是将返回承诺。
即使一个承诺立即解决,async
函数也不会通过设计不返回承诺。
您将不得不等待/使用它。
这在mozilla's JavaScript reference about the async keyword上也有说明:
异步函数声明定义了一个异步函数,该函数 返回一个AsyncFunction对象。异步函数是 通过事件循环异步运行的函数,使用 隐式承诺返回其结果。但是语法和结构 您使用异步功能的代码更像使用标准 同步功能。
特别是关于返回类型:
一个Promise,它将使用异步返回的值来解决 函数,或因内部抛出未捕获的异常而被拒绝 异步功能。
考虑到这一点,建议您将API async
设置为默认值。如果您的某些动作是同步的,那么与外界无关紧要。在这种情况下,您可以立即兑现承诺。不需要您的type StringyThingy = string | Promise<string>;
针对Promise<string>
进行键入,然后让异步处理包装成您的承诺,或者在实际的异步用例中实际返回其他承诺。这样,您不必检查promise的实例,但是您将以相同的方式处理两个异步/同步分支。
如果您真的想要联合体类型(我真的不建议这样做),那么您必须放弃使用async
关键字。
您可以定义返回两种类型的普通函数:
const foo = (x:number): Promise<number>|number => {
if(x >=0) {
return new Promise(resolve => resolve(x));
} else {
return x;
}
}