Typescript 是否支持 ?. 运算符?(它叫什么?)
Typescript 当前是否(或是否有计划)支持
? 的
安全导航
操作符。
即:
var thing = foo?.bar
// same as:
var thing = (foo) ? foo.bar : null;
此外,此操作符是否有更常见的名称(在 Google 上很难找到)。
是的。 从 TypeScript 3.7(于 2019 年 11 月 5 日发布 )开始,此功能受支持,称为 可选链接 :
At its core, optional chaining lets us write code where TypeScript can immediately stop running some expressions if we run into a
null
orundefined
. The star of the show in optional chaining is the new?.
operator for optional property accesses .
有关更多详细信息,请参阅 TypeScript 3.7 发行说明 。
在 3.7 版之前,TypeScript 不支持此功能,尽管早在 Issue 中就有人提出过此要求TypeScript 仓库中的 #16 (可追溯到 2014 年)。
至于 如何称呼这个运算符 ,似乎并没有达成共识。除了“可选链”(在 JavaScript 和 Swift 中也如此称呼)之外,还有其他几个示例:
- CoffeeScript 将其称为 存在运算符 (具体而言,是存在运算符的“访问器变体”):
The accessor variant of the existential operator
?.
can be used to soak up null references in a chain of properties. Use it instead of the dot accessor.
in cases where the base value may be null or undefined .
- C# 将其称为 空条件运算符 。
a null-conditional operator applies a member access,
?.
, or element access,?[]
, operation to its operand only if that operand evaluates to non-null; otherwise, it returnsnull
.
- Kotlin 将其称为 安全调用运算符 。
可能还有很多其他示例。
现在可以了,请参阅 用户“Donut”的回答 。
旧答案: 关于布尔运算符的标准 JavaScript 行为可能有所帮助。布尔方法在比较对象时不返回 true 或 false,但在 OR 的情况下,返回第一个等于 true 的值。
不如单个 ? 那么好,但它有效:
var thing = foo && foo.bar || null;
您可以根据需要使用任意数量的 &&:
var thing = foo && foo.bar && foo.bar.check && foo.bar.check.x || null;
默认值也是可能的:
var name = person && person.name || "Unknown user";
这是在 ECMAScript 可选链式规范中定义的,因此我们在讨论此问题时可能应该参考 可选链式 。可能的实现:
const result = a?.b?.c;
总之,TypeScript 团队正在等待 ECMAScript 规范变得更加严格,以便将来他们的实现不会中断。如果他们现在实施某些功能,那么当 ECMAScript 重新定义其规范时,最终将需要进行重大更改。
请参阅 可选链接规范
如果某些功能永远不会成为标准 JavaScript,则 TypeScript 团队可以根据自己的意愿进行实施,但对于未来的 ECMAScript 添加功能,他们希望保留语义,即使他们提供了早期访问权限,就像他们对许多其他功能所做的那样。
捷径
因此,所有 JavaScript 的时髦运算符都可用,包括类型转换,例如...
var n: number = +myString; // convert to number
var b: bool = !!myString; // convert to bool
手动解决方案
但回到问题。我有一个难以理解的例子,说明如何在 JavaScript(以及 TypeScript)中做类似的事情,尽管我绝对不是说它像你真正想要的功能一样优雅。
(foo||{}).bar;
因此,如果
foo
为
undefined
,则结果为
undefined
,而如果
foo
已定义且具有名为
bar
的属性,该属性具有值,则结果就是该值。
我在 JSFiddle 上放了一个 示例 。
对于较长的示例,这看起来很粗略。
var postCode = ((person||{}).address||{}).postcode;
链式函数
如果您迫切需要较短的版本,而规范仍未确定,我在某些情况下会使用此方法。如果链无法满足或最终为空/未定义,它会评估表达式并返回默认值(请注意,
!=
在这里很重要,我们
不
想使用
!==
因为我们希望在这里进行一些积极的处理)。
function chain<T>(exp: () => T, d: T) {
try {
let val = exp();
if (val != null) {
return val;
}
} catch { }
return d;
}
let obj1: { a?: { b?: string }} = {
a: {
b: 'c'
}
};
// 'c'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = {
a: {}
};
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = {};
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));
obj1 = null;
// 'Nothing'
console.log(chain(() => obj1.a.b, 'Nothing'));