开发者问题收集

Typescript 是否支持 ?. 运算符?(它叫什么?)

2013-03-07
466756

Typescript 当前是否(或是否有计划)支持 ? 的 安全导航 操作符。

即:

var thing = foo?.bar
// same as:
var thing = (foo) ? foo.bar : null;

此外,此操作符是否有更常见的名称(在 Google 上很难找到)。

3个回答

是的。 从 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 or undefined . 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 .

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 returns null .

可能还有很多其他示例。

Donut
2013-03-07

现在可以了,请参阅 用户“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";
A. K-R
2013-03-08

这是在 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;

因此,如果 fooundefined ,则结果为 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'));
Fenton
2013-03-07