ESLint のルールを TypeScript で実装してみる
eslint-plugin-vue-scoped-cssが TypeScript(以下 TS)で書かれていたので、気になったので、TS で ESLint のルールを作成し、プラグインとして公開するまでの手順を紹介する。
実装した repo はこちら
TS で作る環境を整える
- typescript
- eslint
- @types/eslint
- @types/estree
を使う
ts-node は、test のときにあると便利。
TS の module は、ESLint が commonjs でのプラグインを許容してるので、合わせて
"module": "commonjs"
とする。
ルールを作る
@types/eslint
では、namespace でRule
が export されているので、ルール作るときはこれを使う。
型がある程度実装されているので、そこからは JS で書くように普通に実装していく。
ハマったところとしては、
type NodeListener = { [T in NodeTypes]?: (node: ESTree.Node) => void };
となっていて、
import { Rule, RuleTester } from "eslint";
const rule: Rule.RuleModule = {
meta: {...},
create(context) {
return {
Identifier(node) {
if (node.type !== "Identifier") {
return;
}
},
};
},
};
export = rule;
というように、node.type
でタイプガードしないと型が効かないというところだけだった。
テストを書く
mocha を使うので、ts-node に書いてあるように require オプションに ts-node/register を指定してテストを実行する
GitHub - TypeStrong/ts-node: TypeScript execution and REPL for node.js
@types/eslint
では、class でRuleTester
が export されているのでそれを使っていつもどおりテストを書いていく。
build、release する
eslint plugin として公開するときには js にビルドしておかないとダメなので、CI とか手元とかでビルドして npm release する。
以上で終わり。
終わりに
意外と簡単だったが、vue-eslint-parser なんかと組み合わせたらたぶん沼になっていくんだろうなぁという感じ。
TS で ESLint プラグインを作る情報全然見当たらないし知らないので、これから作っていく人はどんどん TS で作って、情報を共有してくれ!!
おまけ
@typescript-eslint/experimental-utils
typescript-eslint がルールを作る際に使用している @typescript-eslint/experimental-utilsは、うまく型を独自で定義してあるっぽかった。
@types/eslint
のかわりにこっちを使っても良さそう。
eslint-ast
ESLint コアメンバーの mysticatea さんの mysticatea/eslint-astでは、AST の型を定義している。
拡張可能な AST の型定義をパッケージ化してみました。いずれ、vue-eslint-parser や @typescript-eslint/parser が作るような付加的な AST の型定義をこれの拡張にしていきたいなぁという気持ち。https://t.co/6mzRJ29dEO
— Toru Nagashima (@mysticatea) April 29, 2020
今後に期待できそう。