sosukesuzuki.dev

August, 12 2024

文字列リテラルから不要なエスケープを取り除くのってリンターの責務かも

Prettier 3.3.3 は、文字列リテラルから不要なエスケープを取り除く。

以下のように:

// Input (3.3.3)
const str = "\a";

// Output (3.3.3)
const str = "a";

このエスケープ(\)は、そのままでは文字列リテラルの中に書けない文字を書くために使われる。たとえばダブルクォートを含む文字列をダブルクォートを使って書くときなど("\"")。この文字列リテラル内の a はそのまま書いたって良いので、全く不要なエスケープである。

この動作に関して、テンプレートリテラルに対しても同じことをするべきじゃないか、という旨のissueが作成された[1]。そう、Prettierは文字列リテラル中の不要なエスケープを取り除くが、テンプレートリテラルに対してはそうしない[2]

// Input (3.3.3)
const tmp = `\a`;

// Output (3.3.3)
const tmp = `\a';

文字列リテラルとテンプレートリテラルの間で動作に一貫性がない、ということになる。

こういうのはできるかぎり一貫していてほしいので、テンプレートリテラル内の不要なエスケープも取り除くように変更しようと考えた[3][4]

しかし、チームで議論した結果、最終的には「そもそも、リテラルから不要なエスケープを取り除くという動作自体、フォーマッタじゃなくてリンターの仕事じゃね?」という結論に至った。つまり、文字列リテラルかテンプレートリテラルかに関わらず不要なエスケープを取り除かない、という方向で一貫性をもたせるということだ。

ということで、そのような方向で進めているのでPrettier 3.3.4からはそのようになる[5]。引き続き同じ動作を期待する場合はESLintのno-useless-escapeなどを使ってほしい。

どうでもいいけど、こういう変更はセマンティックバージョニングにおけるパッチ・マイナー・メジャーのどれでいれるべきなのかいまだにわからない。めんどくさいからパッチでいれる予定だけど。


  1. https://github.com/prettier/prettier/issues/16542 ↩︎

  2. ちなみに、タグ付きテンプレートリテラルの場合は一見不要な \ であってもタグ関数からアクセスできるため、不要ではない(ことがある)。 ↩︎

  3. https://github.com/prettier/prettier/pull/16562 ↩︎

  4. テンプレートリテラルの場合は ${ のエスケープを維持する必要があるので文字列リテラルに対するものとしては若干動作が異なる ↩︎

  5. https://github.com/prettier/prettier/pull/16563 ↩︎