背景
越来越多的前端项目开始使用typescript
这门静态检查语言了,它包括很多很棒的功能点,在这里就不细述,根据静态语法检查和.d.ts
生成的代码提示两大特性,我们就可以来制定并且检查代码规范,现在我们来详细说一下。
代码规范
代码规范大家应该是从开始写第一行代码开始别人就开始和你说,要遵循xx代码规范。公司不同,规范的内容、形式、检查方式也不同,但最终是要验收你的规范。
如果是通过leader code review方式来检查代码,那效率也就太低了,最好的方式就是在GIT提交之前做检查。你的代码不合规范,提交都提交不上去,这样就能从入口上保证代码的规范性。
我们再说看下前端的代码规范情况,前端的代码主要就是js的代码,因为js的灵活性以及随意性,让工具来检查代码的规范成为不可能,这也是我一直头疼的事,因为规范这种东西,说再多遍,不来点强制手段,组内之前也是不可能达成一致的。直到Typescript
的出现,解决了这个问题。
Typescript检查的原理
Typescript
是javascript
的超集,所以ts
在运行之前,得先编译成js
,那么这个编译的过程,ts
的编译引擎就得知道,文件里包括哪些方法,方法包含哪些参数,各参数的定义是什么,类型是什么,总之,所有源信息必须都知道,才能准确无误的把ts
翻译成js
。这些东西也正是我们需要的,通过这些信息,我们就可以对比规范和源信息,来确认是否是符合我们制定规范的代码。
初步实现
顺着这个思路,我查了查typescript
的官方文档,果然找到了一个,叫做Compiler API,最后的那个例子,是和我们的需求相关的,把代码拿下来,也是可以跑通的,所以呢,下一步,就是基于这个例子进行扩展,来满足我们自己的需求。
实现的过程,也是挺痛苦的,因为没有文档,也没有说明,幸亏在vscode
可以点进行看声明文件,好消息是可以看到方法的定义,坏消息就是所有的方法的声明、类型,都没有注释,部分需要自己来猜,哈哈,有总比没有强,照猫画虎,总算实现了基本功能。
官方的.d.ts
大致就长这样
开发之中,有一个问题比较难解决,就是在目前可观测的API中,只能constructor
可以取到返回值类型,其他方法API根本不提供,最后借助stackoverflow
上提问,解决了这个问题,有兴趣的同学可以参考下:how to use typescript Compiler API to get normal function info, eg: returnType/parameters?
检查你的代码
现在已经可以检查你的代码了,我们上面也说了,最好的检查时机是开发人员提交的时候,这时会检查所有的代码,只有所有的代码都符合规范,才会提交成功,这是我们最理想的情况。
按照这个思路,我们可以查到,Git
有很多钩子,pre-commit
、commit-msg
、post-commit
等等,我们使用pre-commit
:提交前检查,会执行.git/hooks/pre-commit
下的脚本文件,但是这个文件分布在组内所有人的笔记本中,并且不能增加版本控制。带着这样的疑问,我们找到了pre-commit
这个神器,它的实现原理也是修改上面的文件,不过它从node
层屏蔽了实现细节,我们只要在package.json
里面增加一个script
就可以实现我们要的功能。
配置大概是这样:
...
"pre-commit": ["commit"],
"script":{
...
"commit": "ts-node verify.ts"
...
}
...
这样在git
里面commit
(不管使用命令行还是SourceTree
这样图形界面)的时候就会执行ts-node verify.ts
,检查要是失败了,就会把错误信息打印到控制台上,并且提交会失败,直到所有的已定规则都验证通过,才会提交成功。
检查失败,大致就是这样的:
还有一个更大的作用
我们已经通过上一步,能够检查我们的规范了,知道代码的所有信息,比如生成.d.ts
文件!对一个对外提供的工具库来讲,如果没有一套完整的.d.ts
文件进行代码提示的话,那就显的太不专业了。如果要生成一个完整的提示文件,就必须要求你的类、方法、参数、返回值都要有完整的注释,这些就应该在你的代码规范中。
我们来看一下,比较好的例子:
知道了所有的信息,生成这个文件其实就是字符串的拼接,没什么技术含量,不过生成的格式还得注意一下。
兼容所有情况的.d.ts
写法
一般我们使用一个库文件的时候,都会有三种用法:
import Util from 'xxx/Util'
import {DateTime, Fiel} from 'xxx/Util'
import * as Util from 'xxx/Util'
在使用的时候,这三种形式所需要的.d.ts
文件的格式也是不一样的,所以作为对外提供服务的库文件来说,所有的使用方式,我们都应该兼容。经过多次尝试,这样格式的.d.ts
文件是兼容所有用法:
export class DateTime {
static dateFormat(....)
}
declare const exDe: {
DateTime: typeof DateTime
}
export default exDe
源码
Demo的源码以及使用效果,用力点我
Demo中用到的代码检查工具,用力点我
使用效果
- 检查失败的情况
- 检查成功的情况
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。