やまどり
import文のごちゃつきはESLintに任せよう

import文のごちゃつきはESLintに任せよう

増えがちなimport文をESLintで自動的に整え、チームでも一貫したコードスタイルを保つための設定方法をFlat Configを使用して解説します。

Share on XShare on Facebook

はじめに

TypeScriptを書いていると、ファイルの先頭にあるimport文がだんだんごちゃついてきます。

import { User } from '@/types/user'
import { useEffect } from 'react'
import { fetchUser } from '../api/user'
import { Button } from '@/components/ui/button'
import { z } from 'zod'
import { unusedFunction } from '@/utils/unused'

外部ライブラリ、エイリアス、相対パス、型importなどが混ざってくると、どこから何を読み込んでいるのか分かりづらくなります。

さらに、使わなくなったimportが残っていることもあります。

import { unusedFunction } from '@/utils/unused'

こういうimport文の整理は、手で頑張るよりESLintに任せたほうが楽です。

今回は、TypeScript環境で次の2つを使ってimport文まわりを整理します。

  • eslint-plugin-import-x
  • eslint-plugin-unused-imports

eslint-plugin-import-xは、eslint-plugin-importのforkで、ES2015以降のimport/export構文をlintし、パスやimport名の間違いを検出するためのプラグインです。READMEでは、依存関係を軽くし、TypeScriptまわりの解決も高速・軽量にすることを目的としていると説明されています。

eslint-plugin-unused-importsは、未使用importを検出して削除するためのプラグインです。READMEでも、未使用のES module importを見つけて削除し、importであればautofixで消せるルールを提供すると説明されています。

つまり、役割としてはこんな感じです。

eslint-plugin-import-x
  → importの順番やグルーピングを整える

eslint-plugin-unused-imports
  → 使っていないimportを消す

手順

まず必要なパッケージを入れます。

Bash
npm install -D eslint @eslint/js typescript-eslint eslint-plugin-import-x eslint-import-resolver-typescript eslint-plugin-unused-imports

eslint-plugin-import-xのTypeScript設定では、eslint-import-resolver-typescriptのインストールが必要とされています。
また、eslint-plugin-unused-importsをTypeScriptで使う場合は、@typescript-eslint/eslint-plugin@typescript-eslint/parserを使うよう案内されています。

typescript-eslintを使う場合は、以下のようにeslint.config.jsを書きます。

eslint.config.js
import js from '@eslint/js'
import { importX } from 'eslint-plugin-import-x'
import unusedImports from 'eslint-plugin-unused-imports'
import tseslint from 'typescript-eslint'

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  importX.flatConfigs.recommended,
  importX.flatConfigs.typescript,

  {
    files: ['**/*.{ts,tsx}'],
    plugins: {
      'unused-imports': unusedImports,
    },
    rules: {
      // importの並び順を整える
      'import-x/order': [
        'error',
        {
          groups: [
            'builtin',
            'external',
            'internal',
            ['parent', 'sibling', 'index'],
            'object',
            'type',
          ],
          'newlines-between': 'always',
          alphabetize: {
            order: 'asc',
            caseInsensitive: true,
          },
        },
      ],

      // 未使用importを削除する
      'no-unused-vars': 'off',
      '@typescript-eslint/no-unused-vars': 'off',
      'unused-imports/no-unused-imports': 'error',
      'unused-imports/no-unused-vars': [
        'warn',
        {
          vars: 'all',
          varsIgnorePattern: '^_',
          args: 'after-used',
          argsIgnorePattern: '^_',
        },
      ],
    },
  },
]

eslint-plugin-unused-importsのREADMEでも、no-unused-varsまたは@typescript-eslint/no-unused-varsをoffにして、unused-imports/no-unused-importsunused-imports/no-unused-varsを使う例が紹介されています。

あとはESLintを実行します。

Bash
npx eslint . --fix

たとえば、次のようなimport文があったとします。

import { User } from '@/types/user'
import { useEffect } from 'react'
import { fetchUser } from '../api/user'
import { Button } from '@/components/ui/button'
import { z } from 'zod'
import { unusedFunction } from '@/utils/unused'

unusedFunctionが使われていなければ削除され、import文もルールに沿って並びます。

import { useEffect } from 'react'
import { z } from 'zod'

import { Button } from '@/components/ui/button'
import { User } from '@/types/user'

import { fetchUser } from '../api/user'

package.jsonにもscriptを用意しておくと便利です。

package.json
{
  "scripts": {
    "lint": "eslint . --fix"
  }
}

これで、手元では次のように実行できます。

Bash
npm run lint

終わりに

import文の順番や未使用importは、コードの動作そのものよりも「読みやすさ」や「差分のきれいさ」に関わる部分です。

だからこそ、人間が毎回気にするよりも、ESLintに任せたほうが楽です。

eslint-plugin-import-xでimportの並び順を整え、eslint-plugin-unused-importsで使っていないimportを消すようにしておけば、import文まわりのごちゃつきはかなり減らせます。

レビューでimport順を指摘する必要もなくなり、不要なimportが残ることも減ります。

import文の整理は、手で頑張るよりESLintに任せましょう。