話說"動態類型一時爽,代碼重構火葬場",雖然有不少不一樣的意見(請參考),但咱們看到勢頭強勁的TypeScript和Flow.js,也能感知到靜態類型在某程度上能幫助咱們寫出更健壯的代碼(固然要基於充分的單元測試上啦)。
ClojureScript與JavaScript同樣採起動態類型,但因爲須要經過Google Closure Compiler編譯後才能運行,所以咱們能夠如同JS那樣藉助GCC的註解來引入編譯時類型檢查,達到一樣靜態類型的效果。html
GCC的編譯時類型檢查僅當optimizations
爲simple
或advanced
時有效。咱們以:cljsbuild
下的dev配置爲例git
:cljsbuild {:builds [{:id "dev" :main type-check.core :output-to "resouces/public/js/type_check.js" :optimizations :simple :source-map "resources/public/js/type_check.js.map" :closure-warnings ;; 設置GCC編譯時類型檢查 {:check-types :warning ;; 務必設置爲warning :undefined-names :off ;; 屏蔽goog庫的異常信息 :externs-validation :off ;; 屏蔽goog庫的異常信息 :missing-properties :off ;; 屏蔽goog庫的異常信息 }}]}
請注意,:check-types
必須設置爲:warning
,若設置爲:error
時,就會報Math.imul引起的JSC_DUP_VAR_DECLARATION_TYPE_MISMATCH異常
,致使項目其餘代碼均不能被編譯。但願大神指點迷津~~github
首先GCC用到的註解語法僅爲JSDoc的子集,因此直接看GCC的註解便可,而ClojureScript通常就用以下幾個chrome
@private {Type} 標識私有成員,且該成員的數據類型 @type {Type} 標識成員的數據類型 @param {Type} varname Description 標識函數的型參的數據類型,參數名和描述 @return {Type} Description 標識函數返回值的數據類型和描述 @throws {Type} 標識函數可能拋出異常類型
接下來就是重點了,咱們寫了這麼多還不就是想引入數據的類型描述嗎?那關鍵就是上述代碼中Type到底應該怎麼寫了!
1.標量類型number
,string
,boolean
,null
,undefined
注意
1、標量類型默認表示變量或參數的實際值爲不可爲null(non-nullable)。若要標識爲可爲null(nullable),那麼只需前置一個問號?
便可(?number
,?string
)
2.對象類型Object
,Function
,Number
,String
,Boolean
,Date
和其餘Cljs或自定義的對象類型。
注意
1、對於非全限定的對象類型,會自動展開爲當前命名空間的類型(如當前命名空間爲my-proj.core
,那麼MyArray
會展開爲my-proj.core/MyArray
)
2、對象類型默認表示變量或參數的實際值可爲null(nullable)。若要標識爲不可爲null(non-nullable),那麼只需前置一個感嘆號!
便可(如!Object
,!Date
等)
3.組合類型,如(number|string)
,便是實際值可爲數字也可爲字符串。
4.集合/字典,Array<Type>
表示爲數組類型且其元素類型能夠繼續遞歸下去,Object<Type>
表示爲對象類型且鍵類型爲Type,Object<Type1,Type2
表示爲對象類型且鍵類型爲Type1而值類型爲Type2
5.函數類型function(Type1,Type2)
,表示函數含數據類型爲Type1和Type2兩個形參。function(Type1,Type2):Type3
,表示函數含數據類型爲Type1和Type2兩個形參,且返回值類型爲Type3。function(...Type)
,表示函數含數據類型爲Type的可變形參,注意可變形參必須做爲最後一個形參出現。function(Type=)
,表示函數含可選的數據類型爲Type的形參,注意可選形參後不能聲明必填的形參。
<font style="color:red">注意注意! </font>數組
@param {function(*,function(*):number)} 是不容許的 @param {function(*,function(*))} 只能這樣寫啦
6.什麼類型均可以,*
函數
1.封裝chrome.runtime.onMessage玩玩單元測試
(defn on-msg "@param {function(*,window.MessageSend,function(*))} handler @return {null}" [handler] (let [this (.. js/chrome -runtime -onMessage)] (.addListener this (fn [a b c] (handler a b c) true))))
<font style="color:red">注意:window.MessageSend
既不是GCC內置的類型也不是咱們自定義類型,而是外部定義的數據類型,所以咱們須要添加externs文件讓GCC識別。</font>
所以獲得的配置以下測試
:cljsbuild {:builds [{:id "dev" :main type-check.core :output-to "resouces/public/js/type_check.js" :optimizations :simple :source-map "resources/public/js/type_check.js.map" :externs ["externs/chrome.js" "externs/chrome_extensions.js"] :closure-warnings ;; 設置GCC編譯時類型檢查 {:check-types :warning ;; 務必設置爲warning :undefined-names :off ;; 屏蔽goog庫的異常信息 :externs-validation :off ;; 屏蔽goog庫的異常信息 :missing-properties :off ;; 屏蔽goog庫的異常信息 }}]}
如官網所講,這部分的內容仍在發展階段,因此還有不少不完善的地方。不過也不影響咱們如今就開始使用,所以良好的代碼註釋歷來都須要的!
尊重原創,轉載請註明來自:http://www.cnblogs.com/fsjohn... ^_^肥仔Johnui
https://clojurescript.org/ref...
https://github.com/google/clo...
https://github.com/google/clo...
https://github.com/google/clo...this