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

ie:

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

此外,这个操作符是否有更常见的名称(很难为谷歌)。


当前回答

更新:是的,现在支持了!

它刚刚与TypeScript 3.7一起发布:https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/

它被称为可选链接:https://devblogs.microsoft.com/typescript/announcing-typescript-3-7/#optional-chaining

有以下内容:

let x = foo?.bar.baz(); 

等价于:

let x = (foo === null || foo === undefined) ?
    undefined :
    foo.bar.baz();

旧的答案

在github上有一个开放的功能请求,你可以在那里发表你的意见/愿望:https://github.com/Microsoft/TypeScript/issues/16

其他回答

我觉得这就是你要找的东西。Powerbite也有类似的例子

/**
 * Type-safe access of deep property of an object
 *
 * @param obj                   Object to get deep property
 * @param unsafeDataOperation   Function that returns the deep property
 * @param valueIfFail           Value to return in case if there is no such property
 */
export function getInSafe<O,T>(obj: O, unsafeDataOperation: (x: O) => T, valueIfFail?: any) : T {
    try {
        return unsafeDataOperation(obj)
    } catch (error) {
        return valueIfFail;
    }
}

//Example usage:
getInSafe(sellTicket, x => x.phoneDetails.imeiNumber, '');

//Example from above
getInSafe(foo, x => x.bar.check, null);

它叫做可选链接,在Typescript 3.7中

可选的链接让我们可以在可以立即停止的地方编写代码 如果遇到null或undefined,运行一些表达式

_。get(obj, 'address.street.name')适用于没有类型的JavaScript。但是对于TypeScript,我们需要真正的Elvis操作符!

我们在开发Phonetradr时创建了这个util方法,它可以让你以类型安全的方式访问Typescript的深层属性:

/** * Type-safe access of deep property of an object * * @param obj Object to get deep property * @param unsafeDataOperation Function that returns the deep property * @param valueIfFail Value to return in case if there is no such property */ export function getInSafe<O,T>(obj: O, unsafeDataOperation: (x: O) => T, valueIfFail?: any) : T { try { return unsafeDataOperation(obj) } catch (error) { return valueIfFail; } } //Example usage: getInSafe(sellTicket, x => x.phoneDetails.imeiNumber, ''); //Example from above getInSafe(foo, x => x.bar.check, null);

正如之前所回答的,目前它仍在考虑中,但到目前为止它已经死在水里几年了。

在现有答案的基础上,以下是我能想到的最简洁的手动版本:

斯菲德尔

function val<T>(valueSupplier: () => T): T {
  try { return valueSupplier(); } catch (err) { return undefined; }
}

let obj1: { a?: { b?: string }} = { a: { b: 'c' } };
console.log(val(() => obj1.a.b)); // 'c'

obj1 = { a: {} };
console.log(val(() => obj1.a.b)); // undefined
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

obj1 = {};
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

obj1 = null;
console.log(val(() => obj1.a.b) || 'Nothing'); // 'Nothing'

它只是在缺少属性错误时无声地失败。它退回到确定默认值的标准语法,也可以完全省略。


虽然这适用于简单的情况,但如果您需要更复杂的东西,例如调用函数然后访问结果上的属性,那么任何其他错误也会被忽略。糟糕的设计。

在上述情况下,这里发布的其他答案的优化版本是更好的选择:

斯菲德尔

function o<T>(obj?: T, def: T = {} as T): T {
    return obj || def;
}

let obj1: { a?: { b?: string }} = { a: { b: 'c' } };
console.log(o(o(o(obj1).a)).b); // 'c'

obj1 = { a: {} };
console.log(o(o(o(obj1).a)).b); // undefined
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

obj1 = {};
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

obj1 = null;
console.log(o(o(o(obj1).a)).b || 'Nothing'); // 'Nothing'

一个更复杂的例子:

o(foo(), []).map((n) => n.id)

你也可以反过来使用类似Lodash' _.get()的东西。它是简洁的,但编译器将无法判断使用的属性的有效性:

console.log(_.get(obj1, 'a.b.c'));