前言

 话说"动态类型一时爽,代码重构火葬场",虽然有很多不同的意见(请参考),但我们看到势头强劲的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. ASP.NET静态化方法

    直接通过访问页面获取html代码实现静态化 突然想到一个静态化页面的方法:直接保存源代码即可. 模拟浏览器访问,获得源码,写入文件.不知道是否存在安全风险:各位大神请指点: 注意 1.资源使用绝对路径 ...

  2. C++重写(override)、重载(overload)、重定义(redefine)以及虚函数调用

    一.基本概念 对于C++中经常出现的函数名称相同但是参数列表或者返回值不同的函数,主要存在三种情况: 1.函数重写(override) 函数重载主要实现了父类与子类之间的多态性,子类中定义与父类中名称 ...

  3. Docker打包 Asp.Net Core应用,在CentOS上运行

    本文主要介绍下运用docker虚拟技术打包Asp.net core应用. Docker作为一个开源的应用容器引擎,近几年得到广泛的应用,使用Docker我们可以轻松实现应用的持续集成部署,一次打包,到 ...

  4. 散列表(拉链法与线性探测法)Java实现

    package practice; import java.security.Principal; import java.util.Scanner; import edu.princeton.cs. ...

  5. 用webgl打造自己的3D迷宫游戏

    用webgl打造自己的3D迷宫游戏 2016/09/19 · JavaScript · WebGL 原文出处: AlloyTeam    背景:前段时间自己居然迷路了,有感而发就想到写一个可以让人迷路 ...

  6. 软件工程(GZSD2015)第二次作业进度

    贵州师范大学软件工程第二次作业 徐 镇 王铭霞 张 英 涂江枫 张 燕 安 坤 周 娟 杨明颢 杨家堂 罗文豪 娄秀盛 周 娟 李盼 岳庆 张颖 李丽思 邓婷 唐洁 郑倩 尚清丽 陈小丽 毛茸 宋光能 ...

  7. 团队项目汇总beta

    一.Daily Scrum Meeting[Alpha] 4.23-第一天 4.24-第二天 4.25-第三天 4.26-第四天 4.27-第五天 4.28-第六天 4.29-第七天 二.Daily ...

  8. Java :内部类基础详解

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 第一次见面 内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类. public class OuterClass { pr ...

  9. 基于图形检测API(shape detection API)的人脸检测

    原文:https://paul.kinlan.me/face-detection/ 在 Google 开发者峰会中,谷歌成员 Miguel Casas-Sanchez 跟我说:"嘿 Paul ...

  10. 安装wampserve之前需要安装vc++2012.

    本人是64位系统下载了wampserver3.0.6之后安装好,启动报错缺少msvcr110.dll. 于是从网上下载了msvcr110.dll放到了windows的syswow64文件夹下,甚至还重 ...