← 記事一覧に戻る

ESLint + Prettier から Biome に移行したら動かない・効かない時の5つの原因と対策【VS Code / CI対応】

ESLint + Prettier から Biome に移行したら動かない

Biome は 2024 年に v1.0 がリリースされた高速な Linter/Formatter で、ESLint + Prettier の代替として注目されています。しかし実際に移行してみると「ルールが全然効かない」「VS Code で自動フォーマットされない」「CI が落ちる」といった問題に直面することが多いです。

よく見るエラー:

$ biome check .
error[migrate]: Rule "no-explicit-any" is not supported. Use "typescript/noExplicitAny" instead.
$ npx biome format --write .
error: Failed to parse configuration from biome.json
  × Unexpected value `tab` at `formatter.indentStyle`

この記事では移行時にハマりやすい 5 つの原因と対策を解説します。

前提:Biome の基本セットアップ

npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init

これで biome.json が生成されます。

{
  "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
  "organizeImports": {
    "enabled": true
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "tab"
  }
}

原因1:VS Code 拡張が ESLint/Prettier のままで Biome 拡張が未インストール

biome check コマンドは通るのに、VS Code でエラーが表示されない・保存しても自動フォーマットされない」というケース。

原因は VS Code の拡張機能設定です。ESLint や Prettier の拡張機能をそのまま使っていて、Biome の拡張機能がインストールされていないため、エディタが Biome を認識できていません。

対策:

  1. VS Code に Biome 拡張機能biomejs.biome)をインストール
  2. .vscode/settings.json を更新する
{
  "editor.defaultFormatter": "biomejs.biome",
  "editor.formatOnSave": true,
  "[javascript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescript]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "biomejs.biome"
  },
  "[json]": {
    "editor.defaultFormatter": "biomejs.biome"
  }
}

重要: ESLint/Prettier の拡張機能を無効化するか、ワークスペースで無効にしましょう。両方有効だとコンフリクトして意図しない動作になります。

チームで共有する場合は .vscode/extensions.json も更新します。

{
  "recommendations": ["biomejs.biome"],
  "unwantedRecommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
}

原因2:package.json の scripts が ESLint/Prettier のまま

CI/CD で「biome を入れたはずなのに、npm run lint が ESLint を呼んでいる」ケース。

// ❌ NG: まだ ESLint/Prettier を呼んでいる
{
  "scripts": {
    "lint": "eslint . --ext .ts,.tsx",
    "format": "prettier --write ."
  }
}

CI 上では ESLint/Prettier がデフォルトで入っていないため、上記のままだと command not found エラーになります。

対策: scripts を Biome に切り替える。

// ✅ OK: Biome に切り替える
{
  "scripts": {
    "lint": "biome lint .",
    "format": "biome format --write .",
    "check": "biome check .",
    "check:ci": "biome ci ."
  }
}

ポイントは CI では biome ci を使うことです。biome check と異なり、biome ci はファイルを書き換えず、差分があった場合に非ゼロ終了コードを返します。biome check を CI で使うとフォーマット差分があっても終了コード 0 になってしまうことがあります。

# .github/workflows/ci.yml
- name: Lint and format check
  run: npx biome ci .

原因3:型を使う ESLint ルールが Biome で動かない

@typescript-eslint/no-floating-promises@typescript-eslint/await-thenable などのルールが移行後に消えた」というケース。

これは仕様です。 Biome v1.x は現時点で TypeScript の型情報を参照するルールをサポートしていません。

型チェックが必要なため Biome に存在しないルールの例:

  • @typescript-eslint/no-floating-promises
  • @typescript-eslint/await-thenable
  • @typescript-eslint/no-misused-promises
  • @typescript-eslint/restrict-template-expressions
  • @typescript-eslint/no-unsafe-assignment

対策: 型チェックが必要なルールのみ ESLint を残す「ハイブリッド構成」にする。

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
// eslint.config.mjs (最小構成:型チェックルールのみ)
import tseslint from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'

export default [
  {
    files: ['**/*.ts', '**/*.tsx'],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: './tsconfig.json',
      },
    },
    plugins: { '@typescript-eslint': tseslint },
    rules: {
      '@typescript-eslint/no-floating-promises': 'error',
      '@typescript-eslint/await-thenable': 'error',
      '@typescript-eslint/no-misused-promises': 'error',
    },
  },
]
// package.json scripts(ハイブリッド構成)
{
  "scripts": {
    "lint": "biome lint . && eslint .",
    "format": "biome format --write .",
    "check:ci": "biome ci . && eslint ."
  }
}

型チェックルールの実行は遅いため、biome lint で高速チェック → eslint で型チェックという順番が効率的です。

原因4:husky / lint-staged の設定が ESLint/Prettier のまま

「コミット時のプリコミットフックで eslint: command not found になる」ケース。

// ❌ NG: lint-staged が ESLint/Prettier のまま
{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"],
    "*.{json,md}": ["prettier --write"]
  }
}

対策: lint-staged の設定を Biome に切り替える。

// ✅ OK: Biome に切り替える
{
  "lint-staged": {
    "*.{js,ts,jsx,tsx,json}": [
      "biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true"
    ]
  }
}

--no-errors-on-unmatched をつけないと、lint-staged が渡すファイルパスが Biome の対象外(例:.md ファイル)だった場合にエラーになります。--files-ignore-unknown=true も合わせて指定することで、未対応ファイルを無視できます。

原因5:biome.json のルール名が ESLint と命名規則が違う

「ESLint のルール名をそのまま biome.json に書いてもエラーになる」ケース。

// ❌ NG: ESLint の命名規則(kebab-case)をそのまま使っている
{
  "linter": {
    "rules": {
      "no-explicit-any": "error",
      "no-unused-vars": "warn"
    }
  }
}
error: Unknown rule "no-explicit-any". Did you mean "typescript/noExplicitAny"?

Biome のルール名は ESLint と命名規則が異なります。ESLint は kebab-case、Biome は カテゴリ/camelCase の形式です。

対策: Biome のルール名に変換する。

// ✅ OK: Biome の形式で記述
{
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true,
      "typescript": {
        "noExplicitAny": "error"
      },
      "correctness": {
        "noUnusedVariables": "warn"
      },
      "suspicious": {
        "noConsoleLog": "warn",
        "noDoubleEquals": "error"
      },
      "style": {
        "useConst": "error",
        "noVar": "error"
      }
    }
  }
}

よく使う ESLint ルールと Biome ルールの対応表:

ESLint ルール Biome ルール
@typescript-eslint/no-explicit-any typescript/noExplicitAny
no-unused-vars correctness/noUnusedVariables
no-console suspicious/noConsoleLog
eqeqeq suspicious/noDoubleEquals
prefer-const style/useConst
no-var style/noVar
no-debugger suspicious/noDebugger
no-alert suspicious/noAlert

全対応表は Biome 公式の Rules Sources ページで確認できます。

まとめ

Biome への移行でよくあるハマりポイントをまとめます。

症状 原因 対策
VS Code で動かない Biome 拡張未インストール 拡張インストール + .vscode/settings.json 設定
CI で lint が通らない scripts が ESLint のまま biome ci . に切り替え
型チェックルールが消えた Biome が型情報非対応 ESLint とのハイブリッド構成
コミット時フックが失敗 lint-staged が古い設定 biome check --apply に更新
ルール設定がエラーになる ルール名の命名規則が違う camelCase の Biome 形式に変換

Biome は ESLint/Prettier より大幅に高速(10〜100 倍)で、設定ファイルも biome.json 1 つで完結します。型チェックルールのみ ESLint をハイブリッドで残せば、ほとんどのプロジェクトで実用的な構成が組めます。ぜひ移行を試してみてください。