如何在TypeScript中检查空值并抛出错误?

36

在 C# 中,我可以编写代码来检查空引用,并在必要时抛出自定义异常,例如:

var myValue = (someObject?.SomeProperty ?? throw new Exception("...")).SomeProperty;

在最近的更新中,TypeScript引入了空值合并操作符"??",但是像上面的语句那样使用会产生编译错误。 在TypeScript中有类似允许的语法吗?


为了澄清,以下代码可以实现所需的行为:

  if(someObject?.someProperty == null) {
    throw new Error("...");
  }

  var myValue = someObject.someProperty.someProperty;

代码:

  var myValue = someObject?.someProperty.someProperty;

逻辑上运行良好,但抛出的异常不够有意义。


那个C#版本不应该只是var myValue = someObject?.SomeProperty ?? throw new Exception("...");吗?或者你是想要获取someObject.SomeProperty.SomeProperty吗? - T.J. Crowder
4个回答

43
只要 TypeScript 没有本地支持,您可以编写一个类似于这个的函数:
function throwExpression(errorMessage: string): never {
  throw new Error(errorMessage);
}

这将允许您将错误作为表达式抛出:

const myString = nullableVariable ?? throwExpression("nullableVariable is null or undefined")

一个抛出异常的辅助函数是一个有趣的方法,谢谢分享! - Valentino Miori
非常好!感谢您的回答。 - Johnny Oshika

23
语法错误的原因是throw是一个语句,因此您不能将其用作运算符的操作数。
有一个JavaScript提案关于throw表达式正在TC39流程中进行,目前处于第二阶段。如果它进入第三阶段,您可以期望不久之后它会出现在TypeScript中。(2020年底更新:然而,它似乎已经停滞不前,由于一个TC39成员在2018年1月阻止了它,认为他们“......如果我们有do表达式,我们就没有足够的动力了......”请注意,do表达式仍然是1阶段,在2020年底,但至少它们在6月提交给了TC39。)
使用throw表达式,您可以编写以下内容(如果您想要someObject.someProperty的值):
const myValue = someObject?.someProperty ?? throw new Error("custom error here");

或者如果你想要someObject.someProperty.someProperty(这应该是你的C#版本做的):

const myValue = (someObject?.someProperty ?? throw new Error("custom error here")).someProperty;

现在有一个Babel插件可以使用。在Babel的REPL上,这是上面的第一个示例


顺便提一下:你说你想抛出一个自定义错误,但是对于其他不需要自定义错误的人来说:

如果你想要someObject.someProperty.someProperty,如果someObjectnull/undefined则不会出错,但是如果someObject.somePropertynull/undefined则会报错,你可以这样做:

const myValue = someObject?.someProperty.someProperty;

因此:

  • 如果someObjectnullundefinedmyValue将获得值undefined
  • 如果someObject不是nullundefinedsomeObject.somePropertynullundefined,由于我们没有在第一个someProperty之后使用?.,您将会收到错误提示。
  • 如果someObjectsomeObject.someProperty都不是nullundefinedmyValue将获得查找someObject.someProperty.someProperty的结果。

2
这个提案已经很久没有进展了,所以我建议在下次会议上删除关于它即将推进的部分。 - Yepeekai
@Yepeekai - 是的,最后一次在2018年提出,被阻止进入第三阶段的共识,并且与此同时,原因(do表达式)仍处于第一阶段。但至少,在2020年6月的会议上介绍了do表达式。 - T.J. Crowder

17
如果你想在一行代码中抛出错误,可以将其包装在立即调用的函数表达式中:

const test = null ?? (() => {throw new Error("Test is nullish")})();


你知道如何设置prettier,使其不会将此重新格式化为多行吗? - undefined

0
我有点晚到派对,但我敢打赌这就是你想要的。我刚把它扔进了我的utils.ts文件中。
export function ensuredDefined<T>(item: T | undefined, message?: string): T {
  if (item === undefined) {
    throw new Error(message ?? 'item is undefined');
  }
  return item;
}

完全透露,我还没有测试过这个,但是我认为这就是你想要的。
所以不是
const color = unusedColors.shift();
if (color === undefined) {
  throw new Error(...);
}
player.color = color;

我有。
player.color = ensuredDefined(unusedColors.shift());

我敢打赌这意味着你会写作。
var myValue = ensureDefined(someObject?.someProperty).someProperty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接