使用 Typescript 檢查你的代碼規範

背景


愈來愈多的前端項目開始使用typescript這門靜態檢查語言了,它包括不少很棒的功能點,在這裏就不細述,根據靜態語法檢查和.d.ts生成的代碼提示兩大特性,咱們就能夠來制定而且檢查代碼規範,如今咱們來詳細說一下。javascript

代碼規範


代碼規範你們應該是從開始寫第一行代碼開始別人就開始和你說,要遵循xx代碼規範。公司不一樣,規範的內容、形式、檢查方式也不一樣,但最終是要驗收你的規範。
若是是經過leader code review方式來檢查代碼,那效率也就過低了,最好的方式就是在GIT提交以前作檢查。你的代碼不合規範,提交都提交不上去,這樣就能從入口上保證代碼的規範性。
咱們再說看下前端的代碼規範狀況,前端的代碼主要就是js的代碼,由於js的靈活性以及隨意性,讓工具來檢查代碼的規範成爲不可能,這也是我一直頭疼的事,由於規範這種東西,說再多遍,不來點強制手段,組內以前也是不可能達成一致的。直到Typescript的出現,解決了這個問題。前端

Typescript檢查的原理


Typescriptjavascript的超集,因此ts在運行以前,得先編譯成js,那麼這個編譯的過程,ts的編譯引擎就得知道,文件裏包括哪些方法,方法包含哪些參數,各參數的定義是什麼,類型是什麼,總之,全部源信息必須都知道,才能準確無誤的把ts翻譯成js。這些東西也正是咱們須要的,經過這些信息,咱們就能夠對比規範和源信息,來確認是不是符合咱們制定規範的代碼。java

初步實現


順着這個思路,我查了查typescript的官方文檔,果真找到了一個,叫作Compiler API,最後的那個例子,是和咱們的需求相關的,把代碼拿下來,也是能夠跑通的,因此呢,下一步,就是基於這個例子進行擴展,來知足咱們本身的需求。
實現的過程,也是挺痛苦的,由於沒有文檔,也沒有說明,幸好在vscode能夠點進行看聲明文件,好消息是能夠看到方法的定義,壞消息就是全部的方法的聲明、類型,都沒有註釋,部分須要本身來猜,哈哈,有總比沒有強,照貓畫虎,總算實現了基本功能。node

clipboard.png

官方的.d.ts大體就長這樣git

開發之中,有一個問題比較難解決,就是在目前可觀測的API中,只能constructor能夠取到返回值類型,其餘方法API根本不提供,最後藉助stackoverflow上提問,解決了這個問題,有興趣的同窗能夠參考下:how to use typescript Compiler API to get normal function info, eg: returnType/parameters?github

檢查你的代碼


如今已經能夠檢查你的代碼了,咱們上面也說了,最好的檢查時機是開發人員提交的時候,這時會檢查全部的代碼,只有全部的代碼都符合規範,纔會提交成功,這是咱們最理想的狀況。
按照這個思路,咱們能夠查到,Git有不少鉤子,pre-commitcommit-msgpost-commit等等,咱們使用pre-commit:提交前檢查,會執行.git/hooks/pre-commit下的腳本文件,可是這個文件分佈在組內全部人的筆記本中,而且不能增長版本控制。帶着這樣的疑問,咱們找到了pre-commit這個神器,它的實現原理也是修改上面的文件,不過它從node層屏蔽了實現細節,咱們只要在package.json裏面增長一個script就能夠實現咱們要的功能。typescript

配置大概是這樣:json

...
"pre-commit": ["commit"],
"script":{
    ...
    "commit": "ts-node verify.ts"
    ...
}
...

這樣在git裏面commit(無論使用命令行仍是SourceTree這樣圖形界面)的時候就會執行ts-node verify.ts,檢查要是失敗了,就會把錯誤信息打印到控制檯上,而且提交會失敗,直到全部的已定規則都驗證經過,纔會提交成功。api

檢查失敗,大體就是這樣的:工具

clipboard.png

還有一個更大的做用


咱們已經經過上一步,可以檢查咱們的規範了,知道代碼的全部信息,好比生成.d.ts文件!對一個對外提供的工具庫來說,若是沒有一套完整的.d.ts文件進行代碼提示的話,那就顯的太不專業了。若是要生成一個完整的提示文件,就必需要求你的類、方法、參數、返回值都要有完整的註釋,這些就應該在你的代碼規範中。

咱們來看一下,比較好的例子:

clipboard.png

知道了全部的信息,生成這個文件其實就是字符串的拼接,沒什麼技術含量,不過生成的格式還得注意一下。

兼容全部狀況的.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中用到的代碼檢查工具,用力點我

使用效果

  • 檢查失敗的狀況

clipboard.png

  • 檢查成功的狀況

clipboard.png

相關文章
相關標籤/搜索