Prettierの「Quote Props」徹底解説:JavaScriptプロパティの引用符をマスターする
Prettierで「Quote Props」という設定は、JavaScriptやTypeScriptなどのオブジェクトリテラルで、プロパティ名をいつ引用符で囲むかを制御します。
より具体的に言うと、オブジェクトのプロパティ名に、引用符で囲む必要がある特殊文字(スペース、ハイフンなど)が含まれていない場合でも、引用符で囲むかどうかを設定するものです。
この設定には、主に以下の3つのオプションがあります。
-
as-needed
(デフォルト):- 説明: プロパティ名がJavaScriptの識別子の命名規則に従っている場合(つまり、特殊文字が含まれていない場合)は引用符を付けません。それ以外の場合(例えば、
"my-property"
のようにハイフンが含まれている場合)は引用符を付けます。 - 例:
// `as-needed` の場合 const obj = { name: "John Doe", age: 30, "first-name": "Jane", // ハイフンがあるので引用符が必要 "last name": "Smith", // スペースがあるので引用符が必要 };
- 特徴: 最も一般的で推奨される設定です。コードが冗長にならず、必要な場合にのみ引用符が付くため、可読性が高いとされています。
- 説明: プロパティ名がJavaScriptの識別子の命名規則に従っている場合(つまり、特殊文字が含まれていない場合)は引用符を付けません。それ以外の場合(例えば、
-
consistent
:- 説明: すべてのプロパティ名で引用符が必要な場合はすべてに引用符を付け、必要ない場合はすべてに引用符を付けません。ただし、これは実際にはほとんどのケースで
as-needed
と同じ動作になります。なぜなら、JavaScriptの仕様上、特殊文字を含むプロパティは常に引用符で囲む必要があるためです。このオプションは、既存のコードベースでas-needed
と異なる挙動を期待する場合に、特定のケースで違いが出る可能性がありますが、通常はas-needed
を選択するのが無難です。 - 例:
as-needed
と同じになることがほとんどです。
- 説明: すべてのプロパティ名で引用符が必要な場合はすべてに引用符を付け、必要ない場合はすべてに引用符を付けません。ただし、これは実際にはほとんどのケースで
-
preserve
:- 説明: 既存のコードのプロパティ名の引用符の状態をそのまま維持します。Prettierはプロパティ名の引用符を変更しません。
- 例:
// `preserve` の場合 // 元のコードが以下の場合 const obj1 = { name: "Alice", "age": 25, // 引用符が付いている }; const obj2 = { "city": "Tokyo", country: "Japan", }; // Prettierを実行しても上記の状態が維持される
- 特徴: 既存の大量のコードがあり、すべてのプロパティ名の引用符のスタイルを一貫させるのが難しい場合や、特定の理由で手動で引用符の有無を制御したい場合に有用です。ただし、新しいコードではスタイルが統一されない可能性があります。
なぜこの設定があるのか?
- 議論の削減: どのプロパティに引用符を付けるべきかという些細な議論をなくし、開発者がより本質的な問題に集中できるようにするためです。
- 可読性: 引用符の有無がランダムだとコードが読みにくくなるため、一貫したルールを適用することで可読性を向上させます。
- 一貫性の維持: コードのスタイルを自動的に統一し、チーム内での認識のずれをなくすためです。
特殊な要件がない限り、Prettierのデフォルト設定であるquoteProps: "as-needed"
を使用することがほとんどの場合で推奨されます。これにより、コードの冗長性が抑えられ、かつ必要に応じて引用符が適切に付与されるため、バランスの取れたコードスタイルが実現できます。
Prettierの設定ファイル(例: .prettierrc
)で以下のように記述して設定できます。
{
"quoteProps": "as-needed"
}
または
{
"quoteProps": "preserve"
}
ESLint と Prettier の設定が衝突する
これは quoteProps
に限らず、Prettier を使用する上で最もよくある問題です。ESLint もコードスタイルに関するルールを持っており、Prettier と同じプロパティの引用符に関するルール (quote-props
) を持っています。この2つのツール間で設定が食い違うと、コードを保存するたびにフォーマットが元に戻ったり、意図しない変更が行われたりします。
一般的なエラーの症状
- CI/CD パイプラインで、Prettier と ESLint のチェックが競合してビルドが失敗する。
- ESLint の警告やエラーが、Prettier でフォーマットしたにもかかわらず表示される。
- ファイルを保存すると、引用符のスタイルが何度も変わる。
トラブルシューティング
-
Prettier と ESLint の設定を同期させる(非推奨だが一時的な解決策)
Prettier のquoteProps
設定と ESLint のquote-props
ルールを一致させる方法です。ただし、この方法はeslint-config-prettier
を使う方がはるかにシンプルで推奨されます。もし Prettier で
quoteProps: "preserve"
を使いたいが、ESLint では常に引用符を付けたい("always"
)というような特殊な要件がある場合は、prettier-eslint
のようなツールを検討することもできますが、複雑さが増します。 -
ESLint の quote-props ルールを無効にする
最も一般的な解決策は、ESLint のquote-props
ルールを無効にするか、Prettier の設定に合わせて調整することです。Prettier はフォーマッターであり、ESLint はリンター(静的コード解析ツール)なので、フォーマットは Prettier に任せるのが理想的です。.eslintrc.js
または.eslintrc.json
に以下を追加します。{ "rules": { "quote-props": "off" // Prettier にフォーマットを任せるため、ESLint のルールを無効化 } }
VS Code などのエディタ設定の競合
Prettier の設定ファイル (.prettierrc
) があっても、VS Code のユーザー設定やワークスペース設定で Prettier 関連のオプションが上書きされている場合があります。
一般的なエラーの症状
.prettierrc
でquoteProps
を設定しているのに、エディタでファイルを保存するとその設定が適用されない。
トラブルシューティング
-
.editorconfig ファイルの確認
プロジェクトに.editorconfig
ファイルが存在する場合、それが Prettier の設定の一部を上書きしている可能性があります。indent_style
やquote_type
のような設定が記述されていないか確認してください。 -
VS Code の設定を確認する
VS Code の設定 (settings.json
) でprettier.quoteProps
などの Prettier 関連の設定が誤って記述されていないか確認します。プロジェクト固有の設定(ワークスペース設定)がユーザー設定を上書きすることがあります。- VS Code で
Ctrl + ,
(Windows/Linux) またはCmd + ,
(macOS) を押して設定を開き、"Prettier" と検索して関連する設定を確認します。
- VS Code で
Prettier のバージョンによる動作の違い
Prettier のバージョンアップによって、一部のオプションのデフォルト値や挙動が変わることがあります。
一般的なエラーの症状
- Prettier をアップデートした後、以前は問題なかったコードの引用符のスタイルが変わった。
トラブルシューティング
-
プロジェクトの Prettier バージョンを固定する
package.json
で Prettier のバージョンを固定し、チームメンバー全員が同じバージョンを使用するようにすることで、バージョンアップによる予期せぬフォーマットの変更を防ぐことができます。{ "devDependencies": { "prettier": "x.y.z" // 具体的なバージョンを記述 } }
-
Prettier の変更履歴を確認する
Prettier の公式ドキュメントやリリースノートで、quoteProps
オプションに関する変更がないか確認します。特にメジャーバージョンアップ(例: Prettier 2.x から 3.x)では、互換性のない変更が含まれることがあります。
Prettier は様々なファイルタイプをサポートしていますが、パーサーの選択やプラグインの有無によって挙動が変わることがあります。
一般的なエラーの症状
- JavaScript/TypeScript ファイルでは
quoteProps
が正しく適用されるが、Vue や Svelte などのSFC(単一ファイルコンポーネント)内のスクリプトブロックで適用されない。
トラブルシューティング
-
パーサーオプションの確認
Prettier が使用するパーサーが、対象のコードを正しく解釈できるか確認します。通常は自動で判断されますが、稀に手動で指定する必要がある場合があります。{ "parser": "typescript" // 必要に応じて指定 }
-
Prettier のプラグインを確認する
特定のフレームワークや言語(例: Vue, Svelte, GraphQL)の構文を正しく解析するためには、追加の Prettier プラグインが必要な場合があります。該当するプラグインがインストールされ、正しく設定されているか確認してください。例: Vue の場合
npm install --save-dev @vue/eslint-config-prettier
それぞれの設定がコードをどのようにフォーマットするか、具体的な例で見ていきましょう。
Prettier の設定ファイル (.prettierrc
) の準備
まず、Prettier の設定ファイル .prettierrc
(または .prettierrc.json
など) を作成し、それぞれのオプションを試せるようにします。
// .prettierrc
{
"quoteProps": "as-needed" // ここを "consistent" や "preserve" に変更して試します
}
例1: quoteProps: "as-needed"
(デフォルト)
これは Prettier のデフォルト設定であり、最も推奨される設定です。プロパティ名がJavaScriptの識別子として有効な場合は引用符を付けず、特殊文字(ハイフン、スペースなど)を含む場合は引用符を付けます。
.prettierrc の設定
{
"quoteProps": "as-needed"
}
フォーマット前のコード (input.js)
const myObject = {
name: "山田",
"age-in-years": 30, // ハイフンがあるので引用符付き
"first name": "太郎", // スペースがあるので引用符付き
isValid: true,
"data": { // 識別子として有効だが、引用符が付いている
"id": 123
}
};
const anotherObject = {
"foo": "bar", // 識別子として有効だが、引用符が付いている
baz: "qux"
};
Prettier でフォーマット後 (npx prettier --write input.js を実行)
const myObject = {
name: "山田",
"age-in-years": 30, // ハイフンがあるので引用符付き (変更なし)
"first name": "太郎", // スペースがあるので引用符付き (変更なし)
isValid: true,
data: { // 識別子として有効なので引用符が除去される
id: 123, // 識別子として有効なので引用符が除去される
},
};
const anotherObject = {
foo: "bar", // 識別子として有効なので引用符が除去される
baz: "qux",
};
ポイント
age-in-years
やfirst name
のように特殊文字を含むプロパティは、引用符が維持されます。name
,isValid
,data
,id
,foo
,baz
はJavaScriptの識別子として有効なため、引用符が除去されます。
例2: quoteProps: "consistent"
この設定は、現在のオブジェクトに引用符が必要なプロパティが一つでもある場合、すべてのプロパティを引用符で囲みます。しかし、実際にはJavaScriptの仕様上、特殊文字を含むプロパティは常に引用符で囲む必要があるため、as-needed
と同様の動作になることがほとんどです。
.prettierrc の設定
{
"quoteProps": "consistent"
}
フォーマット前のコード (input.js)
const myObject = {
name: "山田",
"age-in-years": 30, // ハイフンがあるので引用符付き
isValid: true,
data: {
id: 123
}
};
const anotherObject = {
foo: "bar",
baz: "qux"
};
Prettier でフォーマット後 (npx prettier --write input.js を実行)
const myObject = {
name: "山田",
"age-in-years": 30, // ハイフンがあるので引用符付き (変更なし)
isValid: true,
data: {
id: 123,
},
};
const anotherObject = {
foo: "bar",
baz: "qux",
};
ポイント
- ほとんどの場合、
as-needed
とconsistent
の挙動に違いは見られません。 - この例では
as-needed
と全く同じ結果になります。これは、JavaScriptの仕様上、"age-in-years"
のようなプロパティは常に引用符が必要であり、"consistent"
オプションが「一つでも引用符が必要なプロパティがあればすべてに付ける」という厳密なルールを適用しきれないためです。
この設定は、既存のコードにおけるプロパティ名の引用符の有無をそのまま維持します。Prettierは引用符のスタイルを自動的に変更しません。
.prettierrc の設定
{
"quoteProps": "preserve"
}
フォーマット前のコード (input.js)
const myObject = {
name: "山田", // 引用符なし
"age-in-years": 30, // 引用符あり (ハイフンがあるので必須)
"isValid": true, // 引用符あり (識別子として有効だが、意図的に付けている)
"data": { // 引用符あり
id: 123, // 引用符なし
"category": "A" // 引用符あり
}
};
const anotherObject = {
"foo": "bar", // 引用符あり
baz: "qux" // 引用符なし
};
Prettier でフォーマット後 (npx prettier --write input.js を実行)
const myObject = {
name: "山田", // 引用符なしが維持される
"age-in-years": 30, // 引用符あり (必須なので維持される)
"isValid": true, // 引用符あり (識別子として有効だが、維持される)
"data": { // 引用符あり (維持される)
id: 123, // 引用符なし (維持される)
"category": "A", // 引用符あり (維持される)
},
};
const anotherObject = {
"foo": "bar", // 引用符あり (維持される)
baz: "qux", // 引用符なし (維持される)
};
- この設定は、既存の非常に大きなコードベースがあり、すべてのプロパティの引用符スタイルを統一するのが困難な場合に役立ちます。しかし、新しいコードではスタイルの一貫性が失われる可能性があります。
name
,isValid
,data
,id
,category
,foo
,baz
のすべてのプロパティにおいて、フォーマット前の引用符の有無がそのまま維持されています。
Prettier はコードフォーマッターであり、自動的にスタイルを修正することに特化しています。そのため、quoteProps
の代替方法を考える場合、それは主に「Linter (リンター)」を使ったアプローチと、「手動でのコードスタイル管理」という2つの方向性になります。
リンター (ESLint など) を使用する
Prettier が登場する前から、JavaScript のコードスタイル管理は主にリンター(静的コード解析ツール)の役割でした。ESLint はその代表格です。ESLint には quote-props
というルールがあり、これでプロパティの引用符のスタイルを強制できます。
特徴
- 自動修正 (autofix)
多くのESLintルールは自動修正機能 (--fix
オプション) を持っており、ある程度は Prettier と同様に自動でスタイルを修正できます。 - 警告・エラーとして通知
スタイル違反があった場合、コードの実行前に警告やエラーとして開発者に通知できます。 - より詳細な制御
Prettier のquoteProps
は3つのオプションしかありませんが、ESLint のquote-props
ルールはより細かく設定できます。例えば、キーワードとして予約されているプロパティ名のみ引用符を必須にする、数値のプロパティ名のみ引用符を必須にする、といった設定が可能です。
ESLint の quote-props ルールの設定例
// .eslintrc.json の例
{
"rules": {
// 常に引用符を付ける
"quote-props": ["error", "always"],
// 必要な場合にのみ引用符を付ける (Prettier の as-needed と同等)
// "quote-props": ["error", "as-needed"],
// 識別子として有効なプロパティ名には引用符を付けないが、
// 数字や予約語には付ける(例: "123": "value", "default": "value")
// "quote-props": ["error", "consistent"],
// 識別子として有効なプロパティ名には引用符を付けない
// "quote-props": ["error", "as-needed", { "keywords": false, "unnecessary": true }]
}
}
Prettier との連携に関する注意点
- 推奨されるアプローチ
Prettier を使用している場合は、ESLint のquote-props
ルールを無効化し、Prettier のquoteProps
に任せるのがベストプラクティスです。これはeslint-config-prettier
を利用することで簡単に実現できます。リンターはコードの品質や潜在的なバグの検出に集中し、フォーマットは Prettier に任せる、という役割分担が明確になります。 - 競合を避ける
前述の通り、Prettier と ESLint のquote-props
ルールが競合すると問題が発生します。
手動でのコードスタイル管理とレビュー
これは最も古典的な方法であり、ツールに頼らず開発チームの人間がスタイルガイドに沿って手動でコードを記述・レビューする方法です。
特徴
- ヒューマンエラー
自動化されたツールと異なり、人の手による作業であるため、スタイルの不一致や見落としが発生しやすくなります。 - コスト
チームメンバー全員がスタイルガイドを理解し、一貫して適用するには教育と意識付けが必要です。コードレビューの際にスタイル指摘が増える傾向にあります。 - 柔軟性
どんなルールでも、チームの合意があれば適用できます。 - ツールの導入不要
余計なツールや設定が不要です。
代替方法としての位置づけ
現代のソフトウェア開発では、コードの量や複雑さが増大しているため、手動でのスタイル管理は非効率的であり、エラーの温床となります。そのため、この方法はPrettierやリンターのような自動化ツールの「代替」としては推奨されません。むしろ、自動化ツールを導入する前の段階や、非常に小規模で個人的なプロジェクトでのみ検討されるアプローチです。
一部の統合開発環境 (IDE) やテキストエディタには、独自のコードフォーマッター機能がビルトインされています。例えば、VS Code は JavaScript の基本的なフォーマット機能を持っています。
特徴
- プロジェクト間の不整合
各開発者が異なるエディタや設定を使用している場合、プロジェクト全体でのコードスタイルの統一が困難になります。 - 限定的な機能
通常、カスタマイズ性が低く、Prettier のような高度なフォーマットオプションや、チーム全体での一貫性を強制する機能には劣ります。 - 手軽さ
追加のツールをインストールしなくても、ある程度のフォーマットが可能です。
代替方法としての位置づけ
Prettier が普及する前は、この方法が使われることもありましたが、今ではプロジェクト全体で統一されたフォーマットを実現するために、Prettier のような専用のフォーマッターを導入する方が圧倒的に推奨されます。
Prettier の quoteProps
設定の最も直接的で効果的な代替方法は、ESLint の quote-props
ルールを使用することです。しかし、現代のフロントエンド開発では、フォーマットは Prettier に、コード品質のチェックは ESLint にという役割分担がデファクトスタンダードとなっています。