Typescript中Angular2的Elvis运算符的替换

新手上路,请多包涵

typescript 中是否有任何运算符类似于 angular2 的 Elvis Operator ,我的意思是说假设我必须像这样从对象中获取密钥:

 this.myForm.name.first_name

如果 first_name 不存在,那么它会抛出错误 first_name of undefined

是的,我可以使用 Ternary operator 这样的打字稿来处理这个错误

this.myForm.name ? this.myForm.name.first_name : ''

但有时按键会变得太长,

那么打字稿中是否有像 angular2 的 Elvis Operator 这样的运算符,这样我就可以像这样使用

this.myForm?.name?.first_name

原文由 Pardeep Jain 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 320
2 个回答

2019 年 12 月更新:TypeScript 3.7 引入了可选链接,相当于其他语言中已知的安全导航运算符。 ECMAScript 提案 可选链 已进入第 4 阶段,因此将成为 ES2020 规范的一部分。请参阅 mdn:可选链接 以获取更多信息。


2017 年 7 月更新:正如 JGFMK 在评论中指出的那样,有一个名为 Optional Chaining for JavaScript 的 ECMAScript 提案。如果/当提案到达第 4 阶段时,它将被添加到语言规范中。


TypeScript 中既没有安全导航也没有 elvis 运算符,据我所知,也没有可比性。

有关参考,请参阅 建议中的功能请求:“安全导航运算符”,即 x?.y不执行的解释 如下(我认为这是一个正当理由):

暂时关闭这个。由于实际上没有任何特定于 TypeScript 的内容需要在表达式级别执行此操作,因此这种大的运算符更改应该发生在 ES 规范委员会而不是这里。

重新评估这个的一般绊线将是进入下一阶段的具体 ES 提案,或者 ES 委员会的普遍共识,即该功能不会在很长一段时间内出现(以便我们可以定义自己的语义并合理地确保他们会“赢”)。

该表示法的替代方法是使用逻辑 AND 运算符、try/catch 或类似 getSafe(() => this.myForm.name.first_name) 辅助函数,如 本文 所述。

原文由 str 发布,翻译遵循 CC BY-SA 4.0 许可协议

用一个空对象重复 OR

在编写引用可能存在或不存在的属性/子属性的 HTML 时,我离不开 Elvis。

我们不能写

this.myForm?.name?.first_name

我猜负责 ES 的人可能大部分时间都在实际编写 JS,而不是编写一些访问对象属性的前端 HTML,因此他们对为什么有人需要安全导航感到困惑。

他们争辩说“没有人需要它”,“它允许错误保持沉默,因此以后可能会咬你”和“你会如何解释 x?(y) ?”

在等待未来的 ES 规范包含 Elvis 运算符时,我的解决方案如下:

 (((this.myForm || {}).name || {}).first_name )

简而言之,在一个值可能是 undefined 的每个阶段,你 OR 它与 {} 定义,这样一个空对象就变成了未定义的。一旦将整个内容放入括号中,您就可以安全地尝试提取它的属性,因为您尝试从 {} 中提取的任何属性都只是 undefined 而不是实际错误.

当你有多层时,它确实有点难看,但在许多情况下,它比必须使用一系列 && 逐步降低对象的级别更难看。

对于数组访问,或者它与一个空数组

如果导航到一个数组中,例如,如果表单有很多名称而您想选择第一个,则方法类似:

 ((((this.myForm || {}).names || [])[0] || {}).first_name )

如果链中的某项为 0 或 “” 会怎样?

假设您期望从 this.myForm.names[0].first_name 读取值“John”。

通常会触发错误的典型情况是根本没有对象 this.myForm 。我上面描述的公式不会出错,而是可以工作,并被解释为 {}.first_name ,即 undefined (但不是错误)。

现在想象一个敌对的人偷偷地设置了 this.myForm 到 0 或 “” 或 {}。我们现在会看到错误吗?不,因为值 0 或 “” 被 Javascript 认为是假的,而 {} 是真实的但它本身是 {},所以 this.myForm || {} 评估为 {},并且链的其余部分落入默认值之前,该方法仍然有效,返回 undefined 而不是错误。

例子

 console.log("Each example shows first the result WITH the workaround, and then WITHOUT.")

console.log("a. This should work normally.")
a = { myForm:{ names:[ { first_name:"John", surname:"Smith"}]} };
console.log(a.myForm.names[0].first_name)
console.log ((((a.myForm || {}).names || [])[0] || {}).first_name )

console.log("b. We have removed the first_name property. This still works.")
b = { myForm:{ names:[ {                    surname:"Smith"}]} };
console.log(b.myForm.names[0].first_name)
console.log ((((b.myForm || {}).names || [])[0] || {}).first_name )

console.log("c. We have removed the entire 'names' array. This is fixed by the workaround, but gives an error if run without the workaround.")
c = { myForm:{ } };
console.log ((((c.myForm || {}).names || [])[0] || {}).first_name )
console.log(c.myForm.names[0].first_name)
     console.log("d. Now the whole root object is empty. Again the workaround gets around this, but without the workaround, we get an error.")
    d = { };
    console.log ((((d.myForm || {}).names || [])[0] || {}).first_name )
    console.log(d.myForm.names[0].first_name)

原文由 Eureka 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题