2013-03-07 39 views
96

不打字稿(或者是否有計劃)支持?.Typescript是否支持?運營商? (而且,什麼是它叫什麼名字?)目前

safe navigation操作:

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

此外,有沒有一種比較常見的名字爲這個操作符(這對谷歌來說非常困難)。

+0

我不熟悉操作,但你意思是'var thing = foo?.bar'與'var thing =(foo)相同? foo.bar:null'?換句話說,**如果**(foo),**然後** foo.bar,** else ** null。 – Mathew 2013-03-07 00:38:44

+0

@Mathew Yeah - 另一個例子是:'println company?.address?.street?.name',其中'company','address'或'street'都可以爲空,意味着該語句返回'null'。 – 2013-03-07 01:11:54

+0

@MartyPitt只是指出了在這個問題中的錯字;) – Mathew 2013-03-07 01:17:53

回答

45

我無法在TypeScript language specification中找到任何提及。至於在CoffeeScript中調用這個操作符的內容,它叫做存在操作符(具體來說,是存在操作符的「訪問器變體」)。

CoffeeScript's documentation on Operators

的存在操作者?.的存取變體可以用於在屬性鏈以吸收空引用。在基值可能是nullundefined的情況下,使用它代替點訪問器.

因此,存在操作的訪問變種似乎是指此操作的正確方法;而TypeScript目前似乎不支持它(儘管others have expressed a desire for this functionality)。

+6

「存在操作符的存取器變體」。自然。所以很吸引人,幾乎不可能忘記。 :)。非常全面的答案感謝。 – 2013-03-07 00:35:33

+0

@MartyPitt當然可以!我同意,我希望看到a)更廣泛地採用像這樣的操作符(C#please!)和b)更好的名稱(鏈接的博客文章中的「安全導航」操作符具有良好的響應)。 – Donut 2013-03-07 00:38:14

+3

https://github.com/Microsoft/TypeScript/issues/16問題已移到此處。 – 2015-07-28 20:04:22

19

這是在ECMAScript可選鏈規範中定義的,所以我們在討論這個時可能應該參考可選鏈。可能實現:

const result = a?.b?.c; 

長和短這一個的是,打字稿團隊正在等待ECMAScript規範得到收緊,因此其實施可以是非打破的未來。如果他們現在實現了某些東西,那麼如果ECMAScript重新定義了它們的規範,它將最終需要進行重大更改。

Optional Chaining Specification

如果事情是永遠不會是標準的JavaScript,打字稿團隊可以實現,因爲他們認爲合適的,但對於未來的ECMAScript的增加,他們希望保留即使他們給語義早期訪問,因爲他們有很多其他功能。

走捷徑

因此,所有的JavaScript時髦的運營商可供選擇,包括類型轉換的,如...

var n: number = +myString; // convert to number 
var b: bool = !!myString; // convert to bool 

手動解決方案

但是,回到這個問題。我有一個關於如何在JavaScript中做類似的事情(因此TypeScript)的例子,儘管我絕對不會認爲它是一個非常優雅的特性。

(foo||{}).bar; 

所以,如果fooundefined結果是undefined如果foo被定義並有一個名爲bar具有價值的財產,結果是價值。我想把example on JSFiddle

對於更長的例子,這看起來很粗略。

var postCode = ((person||{}).address||{}).postcode; 

鏈功能

如果你是拼死一較短的版本,而規範仍然在空中,我在某些情況下,使用此方法。它評估表達式,並返回一個默認值,如果鏈不能滿足或結束null/undefined(注意!=在這裏很重要,我們不要想要使用!==,因爲我們希望在這裏有一些積極的雜耍) 。 ?

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')); 
+0

有趣,但在我的情況下'(this.loop || {})。nativeElement'說'屬性'nativeElement'類型'{}'上不存在。任何''this.loop' typeof https://angular.io/api/core/ElementRef – Kuncevic 2017-12-21 04:00:28

+0

@Kuncevic - 你需要...... 1)提供一個兼容的默認值來代替'{}',或者2)使用用於使編譯器無聲的類型斷言。 – Fenton 2017-12-21 09:51:03

+0

(foo || {})。bar; - 耶穌... – 2018-01-07 13:32:37

69

不一樣好作爲一個單一的,但它的工作原理:

var thing = foo && foo.bar || null; 

您可以使用盡可能多的& &,只要你喜歡:

var thing = foo && foo.bar && foo.bar.check && foo.bar.check.x || null; 
+14

&&評估只要聲明是真實的。如果它是真的,它會返回最後一個值。如果它爲假,則返回第一個評估爲false的值。這可能是0,null,false等。 ||返回第一個值爲true的值。 – 2016-03-08 14:29:58

+0

如果欄已定義但評估爲false(如布爾值false或零),則效果不佳。 – 2017-12-14 08:29:32

9

編輯:我已經更新了答案,感謝fracz評論。

打字稿2.0發佈!.這是不一樣的?.(安全Navigator在C#)

看到這個答案的詳細信息:

https://stackoverflow.com/a/38875179/1057052

這隻會告訴編譯器,這個值是不爲空或未定義。這將而不是檢查值是否爲空或未定義。

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 
} 
+0

與'?'不一樣,因爲它*聲明*該值已被定義。預計'?'會默默地失敗/評估爲假。無論如何,很高興知道。 – fracz 2016-11-03 21:08:00

+0

謝謝。讓我編輯! – 2016-11-04 22:54:13

+1

現在我想到了......這個答案是毫無意義的,因爲它不會執行C#操作符所做的「安全導航」。 – 2016-11-04 23:06:00

6

只要我找不到這樣的打字稿, 我用下面的函數的任何信息:

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(o(test).level1).level2).level3 

加,你可以設置一個默認值:

o(o(o(o(o(test).level1).level2).level3, "none") 

它適用於Visual Studio中的IntelliSense。

+1

這正是我期待的!它適用於打字稿2.1.6。 – 2017-03-25 16:50:24

3

我們對Phonetradr工作時,可以給你用的打字稿類型安全的接入到深的屬性創建此util的方法:

/** 
 
* 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);

+0

酷!有什麼需要注意的嗎?我有一個包含大約20個getter的封裝類,每個都有以下類型的返回 - 並且所有的字段都必須是null檢查'return this.entry.fields.featuredImage.fields.file.url;' – Ryan 2018-01-14 11:44:54

+0

The只有警告可能會對性能產生影響,但我沒有資格談論各種JIT的處理方式。 – 2018-02-17 03:43:26