话说"动态类型一时爽,代码重构火葬场",虽然有不少不一样的意见(请参考),但咱们看到势头强劲的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