有一次在寫React的useRef
時,需要將ref
塞進一個HTML element,但我當時還沒有TypeScript的概念,所以,初始化了一個useRef(null)
後,將他塞進一個span
,TypeScript就報錯了,害我當下有點不知所措,所以就google了一下相關資訊,才知道,我應該要先註記他會是特定型別,而那個型別叫HTMLSpanElement
。今天,我們來簡單講講TypeScript要怎麼用在DOM上面吧。
直接來看個例子:
const anchor = document.querySelector("a")
console.log(anchor.href)
我們都知道第一行要選取html中的(第一個)a tag(如果有的話),第二行要印出那個a tag的hypertext reference。如果這兩行是寫在.ts,且我們有在tsconfig.json開啟strictNullChecks
這個flag的話,TypeScript是會報錯的:
Object is possibly 'null'
之所以會這樣,是因為,在寫這幾行code的時,TypeScript不會知道你編譯後的js檔要安插的html檔內,有沒有這樣一個元素,所以TypeScript幫你將anchor
這個變數判斷成HTMLAnchorElement | null
,表示他可能真的是anchor,也可能是null。
這邊我們可以很簡單的用型別防衛去解決這問題:
if(anchor.href){
console.log(anchor.href)
}
但還有更優雅的寫法!(在我們先前的文章中都沒提過)
const anchor = document.querySelector("a")! //最後加個驚嘆號
這個用法叫做"非null值斷言法",只有在你確定null值絕不會發生時才可使用。如果你用了以後,但最後null值還是發生了的話,執行時就會噴錯了。所以,比較安全的做法其實是先前的例子:寫個if
進行型別防衛。
加上驚嘆號後,TypeScript就不會報錯,你就能繼續編譯了。
這時如果我們打上anchor.
,你就能看到一大堆"確定在"a tag能取用的屬性/方法,這種autocomplete超方便的。甚至連已棄用的屬性都能順便列出來給你看。
再來看一下另一個情境,document.querySelector("a")
我們都知道這寫法太籠統了,在開發中應該是透過選擇更有說明意義的class
、甚至是id
,來更精確地選擇到我們要的元素:
const anotherAnchor = document.querySelector(".theanchor")
那這時就有趣了,TypeScript才不會知道.theanchor
是什麼鬼,更不會知道他是什麼型別,也就不可能推薦你anotherAnchor
可以取用的屬性/方法。所以我們可以對anotherAnchor
進行型別斷言。
const anotherAnchor = document.querySelector(".theanchor") as HTMLAnchorElement
便可以解決上述的問題!
既然這邊看到HTMLAnchorElement
了,我們就能推論其他相對應的型別會叫做HTMLSpanElement
或者HTMLFormElement
,我目前沒有仔細查有哪些,但相信要用時再google一定很快。
今天簡單講到這邊,要週一了0rz