default exportはそこまで悪者でもないよ
JavaScript/TypeScriptにおけるdefault exportは使わないようにしている人が少なくないようですし、僕も「named exportを使った方が良いんだ」と思って避けていました。
しかし、最近は「default exportを使っても別に良い」と考えるようになりました。
その辺の話について、雑に書いてみます。
VSCodeのauto import
default exportされたものは、VSCodeでauto importの対象になります。
何年も前からそうだったかは不明ですし、挙動も少しずつ改善されてきたのでしょうが、少なくとも現時点では大きな問題はなさそうです。
基本の動作
次のように、foo.ts
という名前のファイルでdefault exportされたものは、foo
という名前でauto import可能です。
また、foo/index.ts
のようなファイル名や拡張子が.tsxなどの場合も同様です。
export default 'value'
console.log(foo /* ←ここでauto import可能 */)
名前付きの場合
先ほどのように式を直接default exportする場合を、匿名(anonymous) default exportと呼ぶことにします。(変数だけの式は除く)
それに対して、次のような場合を非匿名(non-anonymous) default exportと呼ぶことにします。
(名前付き(named) default exportと呼んでも良いですが、named exportと混同しそうなのでnon-anonymousが良さそう)
// 名前のある関数宣言 (名前: foo)
export default function foo() { }
// 名前のあるクラス宣言 (名前: Foo)
export default class Foo { }
// 変数だけ (名前: value)
export default value
// おまけ:変数だけ (名前: value)
export { value as default }
上に挙げたパターン以外は全て匿名default exportです。
非匿名default exportされたものは、上に書いたようにファイル名を基にした名前の外に、exportされた変数/関数などの名前でもauto importが可能です。
リネーム
VSCodeで非匿名default exportした変数/関数などをリネームすると、同じ名前でimportしている箇所が自動的に変更されます。とても便利。
参照
VSCodeで、default exportされた変数/関数などに対しても、Go references/Find all referencesなどの操作を行うことができます。
匿名の場合はdefault
キーワードをCommand+クリック、または右クリックしてメニューから選択します。
非匿名の場合は、変数/関数名に対して同様のことを行います。
匿名より非匿名のdefault exportを
上で、匿名/非匿名default exportを定義しました。
default exportを使う場合は、可能なら非匿名default exportを使うのが良いと思いました。
理由:
- 意図した名前でauto importできるから
- 匿名default exportを使っていると、
FooBar.ts
をFoo/Bar.ts
に変更するとauto importするための名前が変わってしまう
- 匿名default exportを使っていると、
- リネームするとimport側の名前を変更できるから
- 関数/クラスの場合、意図した名前が付くのでスタックトレースやReact dev toolなどで確認しやすくなるから
ESLintで匿名default exportをチェックする話を最後に書きます。
まとめ
- default exportを使っても、VSCodeのauto importなどの機能を快適に利用できる
- 同じdefault exportでも、匿名と非匿名の2種類がある
- 非匿名default exportがおすすめ
以上です。お読みいただきありがとうございました。
おまけ: ESLintで匿名default exportをチェックしたい
ESLintにno-restricted-exportsというルールがあります。
特定の名前のexportやdefault exportを禁止できるのですが、そこに匿名default exportを禁止するルールを追加するPRを出してみました。
しかし、ESLint本体ではないですが、同じようなチェックを行えるプラグインがありました。(悔しい)
eslint-plugin-importです。
次のように設定します。
{
"plugins": ["import"],
"rules": {
"import/no-anonymous-default-export": ["error", {
"allowCallExpression": false
}]
}
}
Discussion