调用异步函数时遇Type 'void | DiscordServer[]'类型不兼容错误,求解catch块返回值的正确性
问题分析与解决方案
首先,你的初始错误根源在于Promise.catch()块没有返回值,导致整个await表达式的类型变成了DiscordServer[] | void——因为如果find()抛出错误,catch()里的函数默认返回undefined(类型为void),而TypeScript不允许将void | DiscordServer[]赋值给DiscordServer[]类型的变量。
你修改后返回result确实消除了类型错误,但这个方案存在运行时风险,具体原因如下:
- 当
find()抛出错误时,result还未被赋值(因为await的是带catch的Promise,错误被catch捕获后不会执行后续的赋值逻辑),此时result实际上是undefined(虽然你声明了它的类型是DiscordServer[],但TypeScript不会自动初始化变量)。 - 后续代码中直接访问
result[0],如果此时result是undefined,会触发Cannot read properties of undefined (reading '0')的运行时错误。
另外,你的代码同时使用了Promise.catch()和外层的try/catch,属于重复的错误处理逻辑,会让代码逻辑变得混乱。
更安全的解决方案
方案1:统一使用外层try/catch处理错误
既然已经有外层的try/catch,完全可以去掉Promise.catch(),让错误直接冒泡到外层catch块处理,这样类型会自动保持正确:
let result: DiscordServer[]; try { // 移除.catch,让错误进入外层try/catch统一处理 result = await Backendless.Data.of(backendlessDiscordServersTable!).find<DiscordServer>(queryBuilder); if (result[0]) { console.log(result[0].server_id); return result[0].server_id!; } else { console.log('doesnt exist'); return ''; } } catch (error) { // 在这里统一记录并处理错误 writeDiscordLog(filename, functionName, errMsg, error.toString()); throw error; // 如果需要向上抛出错误则保留,否则可省略 }
方案2:若坚持使用Promise.catch(),返回合法默认值
如果你一定要在Promise链内处理错误,应该返回一个符合DiscordServer[]类型的默认值(比如空数组),而非未初始化的result:
let result: DiscordServer[]; try { result = await Backendless.Data.of(backendlessDiscordServersTable!).find<DiscordServer>(queryBuilder) .catch(e => { writeDiscordLog(filename, functionName, errMsg, e.toString()); return []; // 返回空数组,严格匹配DiscordServer[]类型 }); if (result[0]) { console.log(result[0].server_id); return result[0].server_id!; } else { console.log('doesnt exist'); return ''; } } catch (error) { throw error; }
这样做的优势:
- 完全符合TypeScript的类型要求,不会出现类型错误
- 运行时不会出现
undefined相关崩溃,即使错误发生,result也会被赋值为空数组,后续访问result[0]只会得到undefined,不会触发报错
总结
你之前的方案虽然解决了类型错误,但引入了运行时隐患。更合理的做法是要么统一用外层try/catch处理错误,要么在Promise.catch()里返回合法的默认值,避免undefined的出现。
内容的提问来源于stack exchange,提问作者Carlos de la Lama-Noriega
相关产品推荐
相关产品推荐

