距 typescript 3.7
正式發佈已經有一段時間了,這段時間正在對手上的項目進行 typescript
的遷移工做,因此會特別留意每一次的 release
。javascript
對於 3.7
中包含的新特性,其實相比較以前幾回 release
來講,算是一個比較小的發佈版本,可是其中包含的幾個特性對代碼質量自己,會帶來顯著地提高。java
首先第一個特性是對於 optional chaining
操做符的支持,翻譯過來應該能夠叫作可選鏈操做符,固然我仍是以爲這樣翻譯有點怪怪的,暫且就直接用英文好了。typescript
這個特性首先是 es2019
中包含的一個新特性,對於特性自己,有興趣的能夠參考這裏 。json
因爲 typescript
是 javascript
的超集,因此預先實現這個特性也是在預料以內的事情,大概使用方式是這樣的:安全
a?.b();
複製代碼
等價於:bash
if(a) a.b();
// 或者
a && a.b()
複製代碼
若是是多層嵌套,好比 b
也是一個對象,要繼續調用 c()
,那麼能夠這樣:ui
a?.b?.c()
複製代碼
但其實就算這樣寫的話,它也不是安全的,由於 b()
中的 b
也有多是空值,直接調用的話,也會拋出異常。爲了絕對的安全,能夠這樣寫:spa
a?.b?.();
複製代碼
值得注意的是,這裏必定要對於可選的含義有一個正確的理解,可選的意思是,它在類型的聲明中,經過 ?
來修飾,表明一個類型包含某個可爲空值的屬性。言外之意的意思就是,?.
不會對那些不符合類型聲明自己的屬性調用,好比:翻譯
interface A {}
const a: A = {};
a?.b?.(); // Property 'b' does not exist on type 'A'
複製代碼
除非 A
接口的聲明改成:debug
interface A {
b?: any
}
複製代碼
這個特性在項目的實踐意義是很大的,咱們能夠寫更少的 if
斷言語句或者 &&
操做符,可是卻達到了相同的效果。
中文翻譯過來會叫作雙問號操做符,這個其實挺形象的,由於它的語法確實就是 ??
。
這個操做符的功能,往簡單說,就是爲一個空值,指定一個默認值,相似下面的代碼:
let a = b || 'foo'
複製代碼
當 b
爲空值時,因爲 ||
操做符的特性,a
的值會被賦予 foo
。若是使用 ??
操做符進行改寫,以下:
let a = b ?? 'foo'
複製代碼
表面上看,彷佛二者沒什麼區別,但其實這裏隱含了一個問題,就是 ||
對於空值的概念,並不只僅指 null
和 undefined
,相似 false
、0
等一系列邏輯上爲 false
的值都會算做空值,這顯然是有問題的,好比:
const b = 0
let a = b || 'foo'
// a 爲 'foo'
複製代碼
這個示例中,咱們指望 a
只有在 b
爲真正意義上的空值(null
或者 undefined
)時,才被賦予默認值,a
應當等於 0
,而實際運行結果確實 foo
,由於 b=0
,在 ||
操做符的運行過程當中,它會被解釋爲 false
。我曾在實際項目中,編寫過一個驗證碼組件,很不幸,踩上了這個坑,當時爲了 debug
這個問題,花了很長時間。
但使用 ??
操做符,就不會存在這個問題。
我相信不少人都曾經遇過相似的問題,由於缺少有效的命名規範,斷言屬性和斷言方法會在實際項目中被混用,好比:
class A {
isFoo(): boolean {
return false;
}
}
function test(a: A) {
if (a.isFoo) {
...
}
}
複製代碼
這裏若是咱們的本意是要經過調用 a.isFoo
來獲取一個斷言值,咱們明顯犯了一個錯誤,咱們應當使用 if (a.isFoo())
,而不是直接 if (a.isFoo)
,由於後者雖然在語法層面沒有錯誤,可是在邏輯含義,它將被斷言爲 true
。但在 3.7
發佈以後,typescript
會嘗試幫助咱們發現這個問題。
雖然如此,但我仍然建議你們針對斷言方法和斷言屬性制定統一的命名規範,好比 isXXX
表明屬性,而 assertXXX
表明方法。
其餘的一些變動,均是易用性上的一些改變,好比:
Flatter Error Reporting
:會將一大段的類型重複的錯誤日誌,儘量地壓縮爲單條、更準確、更精簡的錯誤日誌@ts-nocheck
:以前版本中該註解僅支持行內級別json
類型js
文件提供 declaration
支持,以減少從 js
項目遷移的遷移成本關注公衆號 全棧 101
,只談技術,不談人生