🤖
Deno で eslint を動かす
deno lint はさすがにルールが足りないので、 eslint も動かせるように確かめたログ。
tl;dr
-
deno run -A npm:eslint
で、型チェックを除く構文周りの lint は動く - deno-lsp の型リゾルバーがないので、
tseslint.configs.strictTypeChecked
は動かない
動かしてみる
ある程度 Node/Deno 互換な範囲の型定義を置く
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"noEmit": true,
"moduleResolution": "bundler",
"strict": true,
"importsNotUsedAsValues": "error",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"allowImportingTsExtensions": true
}
}
node 互換モードで依存をいれる。
$ deno init
$ deno add npm:eslint npm:@eslint/js npm:typescript-eslint npm:eslint-plugin-unused-imports
設定ファイル
eslint.config.ts
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
// フラットコンフィグ対応なら動く
import unusedImports from "eslint-plugin-unused-imports";
// class を禁止するカスタムルール
import { ESLintUtils } from "@typescript-eslint/utils";
export const noClass = createRule({
name: "no-class",
meta: {
docs: {
description: "Disallow the use of class",
},
messages: {
dontUseClass: "Do not use class",
},
type: "suggestion",
schema: [],
},
defaultOptions: [],
create(context) {
return {
ClassExpression(node) {
if (node.id != null) {
context.report({
messageId: "dontUseClass",
node: node.id,
});
}
},
ClassDeclaration(node) {
if (node.id != null) {
context.report({
messageId: "dontUseClass",
node: node.id,
});
}
},
};
},
});
export default tseslint.config(
eslint.configs.recommended,
/// deno lsp がないので、型チェックは不整合になる
// ...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylistic,
/// immport 解決ルールが違うので, eslint-plugin-import もだめだった
// importPlugin.flatConfigs!.recommended,
{
plugins: {
// これは動いた
"unused-imports": unusedImports,
local: {
rules: {
"no-class": noClass,
},
},
},
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
"local/no-class": "error",
},
},
{
rules: {
"@typescript-eslint/no-redeclare": "error",
"@typescript-eslint/prefer-ts-expect-error": "error",
"unused-imports/no-unused-imports": "error",
},
},
);
動かす。
$ deno run -A npm:eslint
/home/mizchi/mizchi/bp/_experimental/deno-eslint/src/fixtures/1.ts
1:1 warning Unused eslint-disable directive (no problems were reported from '@typescript-eslint/no-unused-vars')
2:15 error '_' is defined but never used no-unused-vars
2:15 error '_' is defined but never used
Node 互換 API から叩く
// https://eslint.org/docs/latest/integrate/nodejs-api
import path from "node:path";
import { loadESLint } from "eslint";
const FlatESLint = await loadESLint({ useFlatConfig: true });
const eslint = new FlatESLint({ cwd: Deno.cwd() });
if (import.meta.main) {
const target = Deno.args[0];
const files: string[] = target
? [path.resolve(Deno.cwd(), target)]
: ["src/**/*.ts"];
const results = await eslint.lintFiles(files);
const formatter = await eslint.loadFormatter("stylish");
const resultText = formatter.format(results);
console.log(resultText);
}
動いた。
$ deno run -A run.ts target.ts
感想
構文のみだが、使えなくもない。
型の解決は自分で deno-graph や LSP を繋ぎこみにいってもいいけど、tsgo 前提でエコシステム変わりそうだから、それまで待つ
Discussion