当我从 await 移动到 Promise.all 时,TypeScript 函数 return 类型错误
TypeScript function return type error when I move from await to Promise.all
我有一个功能。 return 类型是用户的承诺:
async function doThing(): Promise<User> {
const one = await getOne();
const two = await getTwo();
return {
one,
two
}
}
我正在更改函数以使用 Promise.all:
async function doThing(): Promise<User> {
const onePromise = getOne();
const twoPromise = getTwo();
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
});
}
但是现在我收到一个 TypeScript 错误:
TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
令我惊讶的是我在代码的第二个版本而非第一个版本中遇到错误。我尝试捕获错误,但没有任何区别:
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
}).catch(error => {
return Error(error);
});
但是在 Promise.all
之后抛出错误确实会使错误消失:
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
});
throw new Error("oh no!")
如@jcalz 所述,您的代码中缺少 return 语句。简短的回答是 .then
return 中的 return
语句仅适用于您在 .then
中定义的函数,而不适用于更大的 doThing
函数。
在 await
、Promise.all
和 Promise.then
都在起作用的情况下,这有点令人困惑,因此我们可以对其进行深入分析。它帮助我隔离方法链中的每个项目并查看它们实际上是什么 return.
但首先,让我们回顾一下这些东西的作用:
Promise.all 将承诺列表 (Promise<any>[]
) 组合为列表承诺 (Promise<any[]>
)。这很方便,允许我们只等待一个承诺来获得我们所有的价值。
Promise.then 允许我们在 Promise 完成后对其进行操作(类似于等待),在这种情况下,将 Promise 转换为不同的类型。这是通过定义一个函数来完成的,该函数接受输入值和 returns 一种新类型的值。请务必注意,该函数内部的 return 语句确定 .then
的 return 值,而不是调用它的函数。
await:Await 从 Promise 中解包一个值。它还会在等待时阻止函数的执行。
所以让我们打破这个链条并添加显式类型来跟随它:
async function doThing(): Promise<User> {
// Promises are created for whatever type getOne and getTwo return, let's say it's any
const onePromise: Promise<any> = getOne();
const twoPromise: Promise<any> = getTwo();
// Promise.all converts a list of Promises (Promise<any>[]) in to a promise of a list (Promise<any[]>)
const allPromises: Promise<any[]> = Promise.all([onePromise, twoPromise]);
// .then convers the Promise of a list (Promise<any[]>) in to a promise of a user (Promise<User>)
// The function inside takes in the unwrapped any[] and returns whatever we want wrapped in a new promise (User, in this case)
// Note that the return here is determining the return value for `.then`, NOT for `doThing` because it is nested inside a separate function.
// `return` statements are subject to scoping rules similar to variable scope
const userPromise: Promise<User> = allPromises.then((values: any[]) => return { values[0], values[1] });
// await unwraps the promised user (Promise<User>) to just a User
const user: User = await userPromise;
// We can now return, this is the line that was missing from your original code.
return user;
}
所以你的 await Promise.all(...).then(...)
链会产生一个 User
对象...但是如果没有 return
或赋值给一个变量,你的函数就不会对它做任何事情。您的代码只需要将 return
添加到该链的前面。
请注意,在我看来,这可以更简单地完成,无需调用 .then
而是等待 Promise.all
async function doThing(): Promise<User> {
const onePromise: Promise<any> = getOne();
const twoPromise: Promise<any> = getTwo();
// Promise.all returns Promise<any[]> and awaiting returns any[]
const values: any[] = await Promise.all([onePromise, twoPromise]);
// Now we can return directly from here
return { values[0], values[1] };
}
另外,为什么抛出一个新错误会停止 TypeScript 错误? TypeScript 错误是由 TypeScript 编译器检测到一个方法会在没有 returning 值的情况下执行到最后时生成的。通过在函数中抛出一个错误,你确保解释器 永远不会 到达函数的末尾而不需要 return... 因为它永远不会到达函数的末尾功能。所以代码是“正确的”,即使它不起作用。
我有一个功能。 return 类型是用户的承诺:
async function doThing(): Promise<User> {
const one = await getOne();
const two = await getTwo();
return {
one,
two
}
}
我正在更改函数以使用 Promise.all:
async function doThing(): Promise<User> {
const onePromise = getOne();
const twoPromise = getTwo();
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
});
}
但是现在我收到一个 TypeScript 错误:
TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
令我惊讶的是我在代码的第二个版本而非第一个版本中遇到错误。我尝试捕获错误,但没有任何区别:
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
}).catch(error => {
return Error(error);
});
但是在 Promise.all
之后抛出错误确实会使错误消失:
await Promise.all([onePromise, twoPromise])
.then(([one, two])=>{
return {
one,
two
}
});
throw new Error("oh no!")
如@jcalz 所述,您的代码中缺少 return 语句。简短的回答是 .then
return 中的 return
语句仅适用于您在 .then
中定义的函数,而不适用于更大的 doThing
函数。
在 await
、Promise.all
和 Promise.then
都在起作用的情况下,这有点令人困惑,因此我们可以对其进行深入分析。它帮助我隔离方法链中的每个项目并查看它们实际上是什么 return.
但首先,让我们回顾一下这些东西的作用:
Promise.all 将承诺列表 (
Promise<any>[]
) 组合为列表承诺 (Promise<any[]>
)。这很方便,允许我们只等待一个承诺来获得我们所有的价值。Promise.then 允许我们在 Promise 完成后对其进行操作(类似于等待),在这种情况下,将 Promise 转换为不同的类型。这是通过定义一个函数来完成的,该函数接受输入值和 returns 一种新类型的值。请务必注意,该函数内部的 return 语句确定
.then
的 return 值,而不是调用它的函数。await:Await 从 Promise 中解包一个值。它还会在等待时阻止函数的执行。
所以让我们打破这个链条并添加显式类型来跟随它:
async function doThing(): Promise<User> {
// Promises are created for whatever type getOne and getTwo return, let's say it's any
const onePromise: Promise<any> = getOne();
const twoPromise: Promise<any> = getTwo();
// Promise.all converts a list of Promises (Promise<any>[]) in to a promise of a list (Promise<any[]>)
const allPromises: Promise<any[]> = Promise.all([onePromise, twoPromise]);
// .then convers the Promise of a list (Promise<any[]>) in to a promise of a user (Promise<User>)
// The function inside takes in the unwrapped any[] and returns whatever we want wrapped in a new promise (User, in this case)
// Note that the return here is determining the return value for `.then`, NOT for `doThing` because it is nested inside a separate function.
// `return` statements are subject to scoping rules similar to variable scope
const userPromise: Promise<User> = allPromises.then((values: any[]) => return { values[0], values[1] });
// await unwraps the promised user (Promise<User>) to just a User
const user: User = await userPromise;
// We can now return, this is the line that was missing from your original code.
return user;
}
所以你的 await Promise.all(...).then(...)
链会产生一个 User
对象...但是如果没有 return
或赋值给一个变量,你的函数就不会对它做任何事情。您的代码只需要将 return
添加到该链的前面。
请注意,在我看来,这可以更简单地完成,无需调用 .then
而是等待 Promise.all
async function doThing(): Promise<User> {
const onePromise: Promise<any> = getOne();
const twoPromise: Promise<any> = getTwo();
// Promise.all returns Promise<any[]> and awaiting returns any[]
const values: any[] = await Promise.all([onePromise, twoPromise]);
// Now we can return directly from here
return { values[0], values[1] };
}
另外,为什么抛出一个新错误会停止 TypeScript 错误? TypeScript 错误是由 TypeScript 编译器检测到一个方法会在没有 returning 值的情况下执行到最后时生成的。通过在函数中抛出一个错误,你确保解释器 永远不会 到达函数的末尾而不需要 return... 因为它永远不会到达函数的末尾功能。所以代码是“正确的”,即使它不起作用。