typescript/no-require-imports 制限
機能
CommonJS の require 呼び出しの使用を禁止します。
なぜ問題なのか?
require によるインポートは、Node.js や古い JavaScript 環境では機能しますが、現代の JavaScript 開発においては、いくつかの重要な理由から、ES モジュール(import)よりも好ましくないとされています。
静的と動的:
requireはランタイム関数です。コードが実行される際に実行されるため、モジュールが見つからない、パスが間違っているなどのエラーは、実行時まで発見されません。一方、ES モジュール(import)は静的インポートです。その解決や潜在的なエラーは、コンパイルまたはバンドルプロセス中に検査されるため、開発段階でより容易に発見できます。コードの構成と可読性:
requireステートメントはコード内に散在しているため、特定のモジュールの依存関係を素早く把握しにくくなる可能性があります。一方、importステートメントは通常、ファイルの先頭にまとめて配置されるため、コードの構成と可読性が向上します。ツリーシェイキングと最適化: 現代のバンドラ(例:Webpack や Rollup)は、ツリーシェイキングにより最終バンドルから未使用コードを削除します。このツリーシェイキングは、依存関係が静的かつ明示的に宣言されている ES モジュールに対して、はるかに効果的です。
requireはバンドラが未使用コードを正確に識別・削除するのを難しくし、結果としてバンドルサイズが大きくなり、読み込み時間が遅くなります。循環依存: 循環依存(モジュール A が B をインポートし、モジュール B が再び A をインポートする)の処理は、
requireを使用する場合、はるかに困難です。一方、宣言的な性質と動的インポート(import())を利用することで、ES モジュールは循環インポートの処理および非同期ロードの管理に優れたメカニズムを提供します。保守性とリファクタリング: モジュール名やパスの変更は、ES モジュールの方が簡単です。変更は直接宣言されるため、コンパイラやバンドラがエラーを検出します。一方、
requireを使用する場合、特定のモジュールに対するすべてのrequireステートメントを追跡して変更する必要があり、リファクタリング時にエラーが生じやすくなります。現代の JavaScript 標準:
importは、現代の JavaScript におけるモジュールインポートの標準的な方法であり、現在のベストプラクティスおよび言語仕様と整合しています。requireを使用するには、ブラウザや現代的な JavaScript 環境が理解できる形式に翻訳するために、追加のビルドステップやツールが必要になります。エラーハンドリング:
try...catchブロックと動的インポート(import())を組み合わせることで、モジュール読み込み時のエラーをより構造的に扱うことができます。これによりエラー管理が強化されます。一方、requireのエラーは予測しづらい場合があります。
要するに、require は動作しますが、静的解析、より良いバンドル、改善されたコード構成、および使いやすさという点で、現代の JavaScript プロジェクトにおけるモジュールインポートの手段として、ES モジュールの方が優れていると言えます。
例
このルールに対して不正なコードの例:
const lib1 = require("lib1");
const { lib2 } = require("lib2");
import lib3 = require("lib3");このルールに対して正しいコードの例:
import * as lib1 from "lib1";
import { lib2 } from "lib2";
import * as lib3 from "lib3";設定
このルールは、以下のプロパティを持つ設定オブジェクトを受け入れます。
allow
type: string[]
default: []
これらの文字列は、u フラグ付きの正規表現にコンパイルされ、インポート先のパスとの照合に使用されます。よくあるユースケースとして、package.json へのインポートを許可することが挙げられます。これは、package.json が一般的に TS ルートディレクトリの外にあるため、静的インポートするとルートディレクトリの衝突が発生する可能性がある(特に resolveJsonModule が有効になっている場合)ためです。また、環境が JSON モジュールをサポートしていない場合に、任意の JSON ファイルのインポートを許可する場合や、import ステートメントが使用できない他のケースにも利用できます。
{ allow: ['/package\\.json$'] } を設定した場合:
このルールに対して正しいコードの例:
console.log(require("../package.json").version);allowAsImport
type: boolean
default: false
true に設定すると、import ... = require(...) の宣言は報告されません。これは、特定のモジュールオプションを使用しており、厳格な CommonJS 互換性のセマンティクスが必要な場合に役立ちます。
true に設定した場合:
このルールに対して不正なコードの例:
var foo = require("foo");
const foo = require("foo");
let foo = require("foo");このルールに対して正しいコードの例:
import foo = require("foo");
import foo from "foo";使用方法
このルールを有効化するには、設定ファイルまたは CLI で以下のように使用できます:
{
"rules": {
"typescript/no-require-imports": "error"
}
}oxlint --deny typescript/no-require-imports