为什么打字稿认为我有一个错误,而它只能是空?

Why does typescript think I have an Error when it can only be null?

提问人:AncientSwordRage 提问时间:11/14/2023 最后编辑:AncientSwordRage 更新时间:11/14/2023 访问量:64

问:

我遇到这种情况,打字稿的行为不符合我的预期(注意。我无法打开整个项目):strictNullChecks

const error = new Error("I'm and error");
const textError = "Also and error";

const printErrorMessage = (err: string | Error) => {
  const errorMessage = (err === null || typeof err === "string") ? err : err?.message ?? err?.name ?? 'unknown error';
  if (errorMessage) {
    console.log(errorMessage);
  }
  return errorMessage;
}

const errorMessageOne = printErrorMessage(error);
const errorMessageTwo = printErrorMessage(textError);
const errorMessageThree = printErrorMessage(null);

我的希望是,唯一返回本身的时间是 if it is 或 a ,但这意味着返回值应该是 或不是 。errnullstringNullstringstring | Error

screenshot of the TS playground, with a tooltip showing the return type is string 'or' Error

因为这个函数可以发送一个空对象,但我不想将其转换为字符串“未知错误”,我不能让空值滑过。

这是我的 TS 游乐场,我已经确认这发生在我的开发环境之外。

TypeScript null 类型缩小

评论

0赞 T.J. Crowder 11/14/2023
您的 Playground 代码与问题中的代码不匹配。在 playground 中,您的参数类型是 ,但在问题的代码中,它只是 。string | Error | nullstring | Error
0赞 AncientSwordRage 11/14/2023
@T.J.Crowder已修复

答:

0赞 Uroš Anđelić 11/14/2023 #1

编辑:@T.J.克劳德的答案是正确的。

我的回答:

如果希望能够传递给函数,则应在函数签名中接受:nullprintErrorMessagenull

const printErrorMessage = (err: string | Error | null) => { ... }

然后,推断的返回类型将为 。string | null

评论

0赞 T.J. Crowder 11/14/2023
他确实在 playground 链接中的函数签名中接受(遗憾的是,不在问题代码中)。null
0赞 AncientSwordRage 11/14/2023
没有,情况就不是这样了strictNullChecks
0赞 Uroš Anđelić 11/14/2023
确实,你们是对的。
2赞 T.J. Crowder 11/14/2023 #2

您需要启用strictNullChecks(我建议通过启用所有选项)。您共享的 Playground 没有它,这就是返回类型为 的原因。如果你启用它,你会得到你所期望的。strict"strict": truestring | Errorstring | null

评论

0赞 AncientSwordRage 11/14/2023
可悲的是,我无法为整个代码库打开,而且我不确定如何只为一行打开。strictNullChecks
1赞 T.J. Crowder 11/14/2023
@AncientSwordRage - 哎哟!我觉得你,遗留代码库是......“有趣”。我很幸运,在严格选项出现并常用之后才开始使用 TypeScript。好消息是,有一种类型谓词解决方法。祝您编码愉快!
0赞 AncientSwordRage 11/14/2023 #3

在发布我的问题并玩了更多之后,我找到了一个临时解决方案(不推荐,但我暂时需要一个权宜之计)。

您可以更改分配行以强制转换(不推荐!)来解决这个问题:const errorMessage = (err === null || typeof err === "string") ? (err as null | string) : err?.message ?? err?.name ?? 'unknown error';

如果可以的话,一定要遵循其他答案。