Edited at

書いて覚える ESLint ルールの作り方:TypeScript で書く


はじめに

前回は一から始めて簡単な ESLint ルールを書きました。

実際に AST を見ながら実用する本命のルールを書いてみると「型がないと木のどの部分を見てるのかわからん…」という気持ちが芽生えてきたので、今回は TypeScript を導入して型推論してもらいながらルールを書く方法を記事にしました。今回はネタは無いです。


どうして TypeScript を使うのか

VSCode で入力補完してくれて、型が間違っている場合はエラーを出してくれるからです。

AST の構造は複雑で、今扱っている変数が Node なのか Property なのかそれとも any なのか考えて書かなければならず、思考の領域を奪われてしまいます。可読性のためにコードの書き方も工夫しないといけないことでしょう。変数の型が一体なんなのかエディタが判別してくれるようにすれば、開発速度が向上します。


TypeScript の導入


パッケージの追加

前回eslintmocha, eslint-plugin-rulesdir に加えて TypeScript で開発するためのパッケージを追加します。

yarn add typescript @types/eslint


tsconfig.json

今回はルールを書くディレクトリを ./rules、TS のトランスパイル出力ディレクトリを ./dist にします。

それ以外の設定はよしなに。とりあえずで作った私の設定は以下の通りです。


tsconfig.json

{

"compilerOptions": {
"outDir": "./dist",
"rootDir": "./rules",
"module": "commonjs",
"target": "es2017",
"noUnusedLocals": true,
"noUnusedParameters": true,
"declaration": true,
"alwaysStrict": true
},
"include": ["rules/**/*"],
"exclude": ["node_modules"]
}


.eslint.js

ルールの本体は js なので、トランスパイル出力ディレクトリを見るようにします。


eslint.js

const rulesDirPlugin = require("eslint-plugin-rulesdir");

rulesDirPlugin.RULES_DIR = "dist";

module.exports = {
plugins: ["rulesdir"],
rules: {
"rulesdir/my-rule": ["error"]
}
};



実装

宣言や型の雰囲気は以下の通りです。


rules/my-rule.ts

import { Rule } from "eslint";

import * as estree from "estree";

const rule: Rule.RuleModule = {
meta: {
schema: [
// よしなに
]
},
create(context: Rule.RuleContext) {
return {
ObjectExpression: (node: estree.Node) => {
// よしなに
}
};
}
};

export = rule;


実装が書けたらトランスパイルはして、dist フォルダに出力されることを確認します。コマンドは次の通りです。

yarn tsc


テスト

そんなに複雑じゃないので前回と同じく js で書きます。この場合、一度トランスパイルしてからテストします。


終わりに

これで TypeScript で ESLint ルールを実装することができるようになりました。型の悩みが軽減されてグッと書きやすくなります。さらに、適当な js ファイルを作って VSCode を再起動して試しにルールを動かしながら開発すると書きやすいですね。