前言

 话说"动态类型一时爽,代码重构火葬场",虽然有很多不同的意见(请参考),但我们看到势头强劲的TypeScript和Flow.js,也能感知到静态类型在某程度上能帮助我们写出更健壮的代码(当然要基于充分的单元测试上啦)。

 ClojureScript与JavaScript一样采取动态类型,但由于需要通过Google Closure Compiler编译后才能运行,因此我们可以如同JS那样借助GCC的注解来引入编译时类型检查,达到同样静态类型的效果。

配置项目设置

GCC的编译时类型检查仅当optimizationssimpleadvanced时有效。我们以:cljsbuild下的dev配置为例

: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异常,导致项目其他代码均不能被编译。希望大神指点迷津~~

注解语法

首先GCC用到的注解语法仅为JSDoc的子集,所以直接看GCC的注解即可,而ClojureScript一般就用如下几个

@private {Type}
标识私有成员,且该成员的数据类型 @type {Type}
标识成员的数据类型 @param {Type} varname Description
标识函数的型参的数据类型,参数名和描述 @return {Type} Description
标识函数返回值的数据类型和描述 @throws {Type}
标识函数可能抛出异常类型

接下来就是重点了,我们写了这么多还不就是想引入数据的类型描述吗?那关键就是上述代码中Type到底应该怎么写了!

1.标量类型number,string,boolean,null,undefined

注意

一、标量类型默认表示变量或参数的实际值为不可为null(non-nullable)。若要标识为可为null(nullable),那么只需前置一个问号?即可(?number,?string

2.对象类型Object,Function,Number,String,Boolean,Date和其他Cljs或自定义的对象类型。

注意

一、对于非全限定的对象类型,会自动展开为当前命名空间的类型(如当前命名空间为my-proj.core,那么MyArray会展开为my-proj.core/MyArray

二、对象类型默认表示变量或参数的实际值可为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的形参,注意可选形参后不能声明必填的形参。

注意注意!

  1. 形参和逗号间千万不要留空格,否则编译时会报警告的哦!
  2. Type为function()时不能在声明返回值类型,否则编译时辉报警告!
@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))))

注意:window.MessageSend既不是GCC内置的类型也不是我们自定义类型,而是外部定义的数据类型,因此我们需要添加externs文件让GCC识别。

因此得到的配置如下

: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/fsjohnhuang/p/7625414.html _肥仔John

参考

https://clojurescript.org/reference/compile-time-type-checking

https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler

https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System

https://github.com/google/closure-compiler/wiki/Warnings

编译期类型检查 in ClojureScript的更多相关文章

  1. Java 泛型优点之编译时类型检查

    Java 泛型优点之编译时类型检查 使用泛型代码要比非泛型代码更有优势,下面是 Java 官方教程对泛型其中一个优点的介绍: "Stronger type checks at compile ...

  2. 数值类型中JDk的编译期检查和编译期优化

    byte b1 = 5;//编译期检查,判断是否在byte范围内 byte b2 = 5+4;//编译期优化,相当于b2=9 byte b3 = 127;//编译通过,在byte范围内 byte b4 ...

  3. 通过宏封装实现std::format编译期检查参数数量是否一致

    背景 std::format在传参数量少于格式串所需参数数量时,会抛出异常.而在大部分的应用场景下,参数数量不一致提供编译报错更加合适,可以促进我们更早发现问题并进行改正. 最终效果 // 测试输出接 ...

  4. 类型检查和鸭子类型 Duck typing in computer programming is an application of the duck test 鸭子测试 鸭子类型 指示编译器将类的类型检查安排在运行时而不是编译时 type checking can be specified to occur at run time rather than compile time.

    Go所提供的面向对象功能十分简洁,但却兼具了类型检查和鸭子类型两者的有点,这是何等优秀的设计啊! Duck typing in computer programming is an applicati ...

  5. java编译期优化

    java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程: 1.前端编译:把.java文件转变为.class文件 2.后端编译:把字节码转变为机器码 3.静态提前编译:直接把*.ja ...

  6. JVM-程序编译与代码早期(编译期)优化

    早期(编译期)优化 一.Javac编译器 1.Javac的源代码与调试 Javac的源代码放在JDK_SRC_HOME/langtools/src/shares/classes/com/sun/too ...

  7. Javac早期(编译期)

    从Sun Javac的代码来看,编译过程大致可以分为3个过程: 解析与填充符号表过程. 插入式注解处理器的注解处理过程. 分析与字节码生成过程. Javac编译动作的入口是com.sun.tools. ...

  8. 读书笔记 effective c++ Item 41 理解隐式接口和编译期多态

    1. 显示接口和运行时多态 面向对象编程的世界围绕着显式接口和运行时多态.举个例子,考虑下面的类(无意义的类), class Widget { public: Widget(); virtual ~W ...

  9. 介绍几款 Python 类型检查工具

    近日,微软在 Github 上开源了一个 Python 静态类型检查工具:pyright ,引起了社区内的多方关注. 微软在开源项目上的参与力度是越来越大了,不说收购 Github 这种大的战略野心, ...

随机推荐

  1. 开源分享 Unity3d客户端与C#分布式服务端游戏框架

    很久之前,在博客园写了一篇文章,<分布式网游server的一些想法语言和平台的选择>,当时就有了用C#做网游服务端的想法.写了个Unity3d客户端分布式服务端框架,最近发布了1.0版本, ...

  2. JQuery的动态加载class无法实现点击时间的解决方案

    //对于 加载过来class 的del_a 实现点击事情 $(document).on('click',".del_a",function(){ $(".mark_id& ...

  3. log4j与log4j.properties的配置

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt233 摘要: 一.配置步骤 1.  在应用程序中使用log4j 2.  把l ...

  4. 第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)

    目标: 1.关看门狗 2.设置时钟 3.初始化SDRAM (初始化寄存器以及清除bss段) 4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash) 5 ...

  5. CurrentCulture和CurrentUICulture的区别

    CurrentCulture 这个属性用来表示和改变使用者要使用的“地区属性”,地区属性改变后,数字.日期时间等表示格式也随之改变. 注意:一定是“地区属性”,如"zh-cn".& ...

  6. 你所不知道的 CSS 滤镜技巧与细节

    承接上一篇你所不知道的 CSS 动画技巧与细节,本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! OK,下面直接进入正文.本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE ...

  7. Spring集成RabbitMQ-连接和消息模板

    ConnectionFactory ConnectionFactory是RabbitMQ服务掌握连接Connection生杀大权的重要组件 有了它,就可以创建Connection(org.spring ...

  8. 【1414软工助教】团队作业6——展示博客(Alpha版本) 得分榜

    题目 团队作业6--展示博客(Alpha版本) 作业提交情况情况 为所欲为 团队没有提交,其余都按时提交. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2: ...

  9. 201521123024《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 注意conve ...

  10. 201521123087《Java程序设计》 第八周学习总结

    1. 本周学习总结 2. 书面作业 本次作业题集集合 List中指定元素的删除(题目4-1)1.1 实验总结                                               ...