Typescript目前(或有计划)是否支持?.
的{{3}}运算符
即:
var thing = foo?.bar
// same as:
var thing = (foo) ? foo.bar : null;
此外,这个运营商是否有一个更常见的名称(它很难谷歌)。
答案 0 :(得分:118)
不如单身好吗?但它有效:
var thing = foo && foo.bar || null;
你可以使用尽可能多的&&如你所愿:
var thing = foo && foo.bar && foo.bar.check && foo.bar.check.x || null;
答案 1 :(得分:80)
我在TypeScript language specification中找不到任何引用。
至于在CoffeeScript中调用此运算符的内容,它被称为存在运算符(具体地说,是存在运算符的“存取变量”)。
来自CoffeeScript's documentation on Operators:
存在运算符
?.
的访问器变体可用于在属性链中吸收空引用。如果基值可能 null 或未定义,请使用它代替点访问器.
。
因此,存在运算符的存取器变体似乎是引用此运算符的正确方法;和TypeScript目前似乎不支持它(尽管others have expressed a desire for this functionality)。
答案 2 :(得分:59)
这是在ECMAScript可选链接规范中定义的,因此在讨论时我们应该参考可选链接。可能的实施:
const result = a?.b?.c;
这一点的长短之处在于TypeScript团队正在等待ECMAScript规范收紧,因此它们的实现在未来可能不会中断。如果他们现在实现了某些东西,那么如果ECMAScript重新定义他们的规范,最终将需要进行重大改变。
请参阅Optional Chaining Specification
在某些东西永远不会成为标准JavaScript的情况下,TypeScript团队可以在他们认为合适的情况下实现,但是对于未来的ECMAScript添加,他们希望保留语义,即使它们提供早期访问,因为它们具有许多其他功能。
因此所有JavaScripts时髦运算符都可用,包括类型转换,如...
var n: number = +myString; // convert to number
var b: bool = !!myString; // convert to bool
但回到这个问题。我有一个很明显的例子,说明你如何在JavaScript(以及TypeScript)中做类似的事情,虽然我绝对不会暗示它是一个优雅的,因为你真正追求的功能。
(foo||{}).bar;
因此,如果foo
为undefined
,则结果为undefined
,如果foo
已定义并且具有名为bar
的属性具有值,则结果为是那个价值。
对于较长的例子,这看起来很粗略。
var postCode = ((person||{}).address||{}).postcode;
如果您在规格尚未播出时急需较短的版本,我会在某些情况下使用此方法。它评估表达式并返回默认值,如果链不能满足或结束null / undefined(注意!=
在这里很重要,我们不想要使用{{ 1}}因为我们想要一些积极的玩杂耍。)
!==
答案 3 :(得分:30)
github上有一个开放的功能请求,您可以在其中表达您的意见/愿望:https://github.com/Microsoft/TypeScript/issues/16
答案 4 :(得分:18)
编辑:由于fracz评论,我已经更新了答案。
TypeScript 2.0发布!.
它与?.
(C#中的安全导航器)不同
有关详细信息,请参阅此答案:
https://stackoverflow.com/a/38875179/1057052
这只会告诉编译器该值不为null或未定义。这将不检查值是null还是未定义。
TypeScript Non-null assertion operator
// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
// Throw exception if e is null or invalid entity
}
function processEntity(e?: Entity) {
validateEntity(e);
let s = e!.name; // Assert that e is non-null and access name
}
答案 5 :(得分:11)
TypeScript 3.7支持Elvis(?。)可选链接运算符。
您可以使用它来检查null值:如果cats为null或未定义,cats?.miows
返回null。
您也可以将其用于可选的方法调用:cats.doMiow?.(5)
将调用doMiow(如果存在)。
还可以访问属性:cats?.['miows']
。
参考:https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-beta/
答案 6 :(得分:6)
TypeScript 版本2.0 不支持运算符?.
。
所以我使用以下功能:
export function o<T>(someObject: T, defaultValue: T = {} as T) : T {
if (typeof someObject === 'undefined' || someObject === null)
return defaultValue;
else
return someObject;
}
用法如下:
o(o(o(test).prop1).prop2
加上,您可以设置默认值:
o(o(o(o(test).prop1).prop2, "none")
它在Visual Studio中与IntelliSense配合得很好。
答案 7 :(得分:2)
这称为可选链接,位于Typescript 3.7
中可选链接使我们可以编写代码,以便立即停止 如果遇到null或未定义,则运行一些表达式
答案 8 :(得分:1)
我们在使用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);
答案 9 :(得分:1)
我通常不推荐这种方法(注意性能问题),但是您可以使用spread运算符来浅克隆对象,然后可以访问该对象。
class UserDetails(viewsets.ModelViewSet):
def get_queryset(self):
user_id = self.request.query_params.get('user_id')
if user_id:
return UserModel.objects.filter(id=user_id).first()
return UserModel.objects.none()
之所以可行,是因为“名字”的类型是“传播”到的。
当我有一个 const person = { personId: 123, firstName: 'Simon' };
const firstName = { ...person }.firstName;
表达式可以返回null并且需要一个单独的属性时,我会经常使用它:
find(...)
打字稿可能会在某些情况下推断类型,因此无法编译,但这通常可以正常工作。
答案 10 :(得分:1)
终于来了!
以下是一些示例:
// properties
foo?.bar
foo?.bar()
foo?.bar.baz()
foo?.bar?.baz()
// indexing
foo?.[0]
foo?.['bar']
// check if a function is defined before invoking
foo?.()
foo.bar?.()
foo?.bar?.()
但这与您的假设并不完全相同。
而不是评估
foo?.bar
对于这个小代码段,我们都习惯于编写
foo ? foo.bar : null
它实际评估为
(foo === null || foo === undefined) ?
undefined :
foo.bar
适用于所有falsey值,例如空字符串,0或false。
对于他们为什么不将其编译为foo == null
答案 11 :(得分:0)
如前所述,它目前仍在考虑中,但到目前为止已经考虑了has been dead in the water。
在现有答案的基础上,这是我能想到的最简洁的手册版本:
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'));
答案 12 :(得分:0)
_.get(obj, 'address.street.name')
非常适合没有类型的JavaScript。但是对于TypeScript,我们需要真正的Elvis运算符!
答案 13 :(得分:0)
尚未(截至2019年9月),但是自“安全导航操作员” is now at Stage 3起,它已在TypeScript中实现。
观看此问题以获取更新:
https://github.com/microsoft/TypeScript/issues/16
几个引擎有较早的实现:
JSC:https://bugs.webkit.org/show_bug.cgi?id=200199
V8:https://bugs.chromium.org/p/v8/issues/detail?id=9553
SM:https://bugzilla.mozilla.org/show_bug.cgi?id=1566143
(通过https://github.com/tc39/proposal-optional-chaining/issues/115#issue-475422578)
您现在可以安装一个插件来支持它:
npm install --save-dev ts-optchain
在您的tsconfig.json中:
// tsconfig.json
{
"compilerOptions": {
"plugins": [
{ "transform": "ts-optchain/transform" },
]
},
}
我希望这个答案在接下来的6个月左右会过时,但希望它能在此期间对某人有所帮助。
答案 14 :(得分:0)
我想这就是你要找的。 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);
答案 15 :(得分:-8)
在2.9版中支持! https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#non-null-assertion-operator
const a = {}
console.log(a!.b!.c)
.tsconfig中不需要任何其他选项