TS/JSでセミコロンをつけないスタイル(No-Semi)について
TypeScriptやJavaScriptにおいて、文末にセミコロンをつけないスタイル(以下「No-Semiスタイル」)の現在の普及状況について、最近の調査資料が見つからなかったため、独自に調べてみました。コーディングスタイルを検討する際の参考になれば幸いです。
背景
Cursor ComposerやClineなどのコーディングAIを使ってTypeScriptの開発をしていると、Lint設定でNo-Semiスタイルを指定しているにもかかわらず、Composerがセミコロンありのコードを生成してしまうため、毎回Lintエラーが発生することがあります。
この問題は「TypeScriptではNo-Semiスタイルを採用する」とカスタムプロンプトに明記することで回避可能です。しかし、デフォルトのスタイルとしてセミコロンありが採用されていることには少し違和感がありました。
いつからかは定かではありませんが、私自身はTypeScriptやJavaScriptを書く際には自然とNo-Semiスタイルをとるようになっています。周りのプログラマにヒアリングしてみても、TypeScriptでNo-Semiスタイルを採用しているケースは少なくありません。
この背景には、最近のWeb開発スタックにNo-Semiスタイルが多く取り入れられていることがあると考えられます。たとえば以下のようなプロジェクトでは、公式ドキュメントのコード例にセミコロンがないものを目にします。
以下はNext.jsの公式サイトのサンプルです。
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
少し調べてみると、JavaScriptコミュニティ全体としては「セミコロンを付ける/付けないは好みの問題」という認識が定着しているようです。しかし、具体的にどれくらいNo-Semiスタイルが採用されているのか、あるいは増加傾向にあるのかを示すような調査はあまり見当たりませんでした。
そこで本記事では、No-Semiスタイルの発生と普及、これまでの議論を簡単にまとめるとともに、実際の採用率に関する調査結果をご紹介します。
No-Semiスタイルの発生と普及
JavaScriptは文末に必ずしもセミコロンを必要としません。これは「自動セミコロン挿入(ASI)」と呼ばれる仕様によるもので、必要な箇所にはインタプリタが自動的にセミコロンを補完します。このため、意図的に文末のセミコロンを省略するNo-Semiスタイルが登場し、賛否両論ありつつも徐々に受け入れられてきました。
1997年の初版から続くECMAScript/JavaScriptの仕様においては、基本的に文末のセミコロンは任意です。改行によって文の終了が認識される場合、JavaScriptエンジンは自動的にセミコロンを挿入してくれるため、JavaScriptでは当初からセミコロンは「省略可能」でした。
一方で、長い間JavaScriptコミュニティでは「セミコロンを常につける」スタイルが主流でした。Googleのスタイルガイドをはじめ、影響力のあるガイドラインが「セミコロンあり」を推奨していた影響も大きいと思われます。
しかし、2010〜2012年ごろから一部の開発者が「ほとんどの場合、セミコロンは省略できる」と主張し始めました。StackExchangeなどで熱い議論が交わされましたが、最終的にはNo-Semiスタイルが実験的な流行から主要プロジェクトでも採用される「有力なスタイルのひとつ」へと成長していきます。
No-Semiスタイルの台頭には、以下のような要因が関係していると考えられます。
1. 開発エコシステムの成熟
以前は文末にセミコロンを付けなければ誤動作を引き起こすツール(たとえばUglifyJSの初期バージョンなど)も存在しました。しかし、現在のJavaScriptエコシステム全体が成熟するにつれ、こうしたツールは改善されたり淘汰されていきました。これによって「バグを防ぐためにセミコロンをつけるべきだ」という主張の根拠は弱くなりました。
2. StandardJS
2015年に登場したZero ConfigurationのLinterであるStandardJSは、デフォルトでセミコロンを付けないルールを採用しています。これをきっかけに、多くのNode.jsやオープンソースプロジェクトがNo-Semiスタイルを意識するようになりました。
3. Prettier
2017年に登場したPrettier(コードフォーマッター)は、設定次第でセミコロンの有無を自動で処理できます。これによって「セミコロンを付ける/付けない」の議論そのものがツールの設定で完結するようになり、スタイル選択の自由度が高まりました。
4. TypeScriptの影響
TypeScriptはJavaScriptのスーパーセットで、ASIもそのまま利用できるためセミコロンは必須ではありません。さらにTypeScriptのコンパイラが改行による意図しない挙動(例:return
とオブジェクトリテラルを改行して書くケース)を検知しやすくすることもあり、No-Semiスタイルを安心して採用できる下地が整っています。
現在のNo-Semiの普及率調査
TypeScript/JavaScriptを使ったGitHubの人気リポジトリを対象に、PrettierのNo-Semi設定(semi: false
)を採用している割合を調べました。期間はPrettierが一般に認知され始めた2017年以降で、TypeScript・JavaScriptそれぞれスター数の多い上位100プロジェクトをリストアップし、Prettierの設定ファイルを確認できたものを対象としています。
調査結果は以下のとおりです。(調査日:2025年2月24日)
言語 | Repos | Prettier採用数 | Semi | No-Semi | 普及率 |
---|---|---|---|---|---|
TypeScript | 100 | 90 | 72 | 18 | 20.0% |
JavaScript | 100 | 70 | 65 | 5 | 7.1% |
合計 | 200 | 160 | 137 | 23 | 14.4% |
上記を見ると、TypeScriptのほうがNo-Semiスタイルの採用率は高く、20%ほどがNo-Semiを設定していました。一方でJavaScriptでは約7%にとどまっており、総合では14.4%がNo-Semiを選択しているという結果でした。
まとめ
- JavaScriptはもともと自動セミコロン挿入(ASI)を備えており、セミコロンは必須ではない
- 近年、標準LintとしてのStandardJSやコードフォーマッターのPrettierが普及したことで、No-Semiスタイルを含む多様なコーディングスタイルが採用されやすくなった
- TypeScriptでもNo-Semiスタイルは有力な選択肢のひとつとして定着しつつあり、人気プロジェクトの2割ほどで採用されている
No-Semiスタイルはセミコロン不要でコードがスッキリするといった利点がある一方、好みやチームの方針、他のツールやコンベンションとの整合性などを踏まえる必要があります。
No-SemiかSemi付きかにはコミュニティにおいては「好みの問題である」という結論が出ていることを前提に、最終的にはプロジェクトやチームの合意のもとでスタイルを決め、PrettierやESLintなどのツールで一貫性を保つのが望ましいでしょう。
Discussion
TSでのno-semi、確かになと思って読んでました。事前にシンタックスがチェックされるのでセミコロンつけないことで起きる諸問題も回避できますし、トランスパイルもされるので。
ただ、JSのほうは以前semiのほうが良いんじゃないかなと思いました。静的型検査されないので 諸問題 が起きる可能性があります。
そもそも、TSがない時代のJSにおいてセミコロン派が主流だったのは、自分のJSスクリプトのあとに実行されるJS、前に実行されたJSの影響を受ける可能性がある、というのも理由の一つだったと思います。(
const x = someFunc()
のあとに(function(){})()
が読み込まれるとエラーになるなど)いまは各バンドラ、ビルドツール側である程度配慮されているはずだから問題は減ったとはいえ、上にあげた問題をすべては回避できないので、JSに関してはつけたほうが楽なんじゃないかなと思いました。
蛇足ですが、弊社Nuxt(TypeScript)テンプレートの前身では
していると、以下に自動整形されていた気がします。
eslintでも自動フォーマットさせていたので、いずれかのルールがやってくれていたのかもしれません。
参考までに、現行の弊社Nuxt(TypeScript)テンプレートを上げておきます。
ただしまだ開発中であり、自動フォーマット周りが怪しいので、上記のフォーマットはしてくれないかもしれません。
eslint「あ、あれ? わいは…?」
なお当のJavaScript作者はASIやめときゃよかった…と後悔している。
例えばここに No-Semi スタイルで書いた分割代入のサンプルコードがある。
おやおや、スタイルに反して「通常の代入」行にセミコロンが混入していますよ……と思ってセミコロンを削除するとこのコードは正しく動作しなくなる。
No-Semi スタイルでも、このセミコロンは必須である。
(セミコロンが無いと「a = "hoge"[b, c] = ["fuga", "piyo"]」だと解釈されるので)
もちろん、こんな問題があるという議論も尽くされた末にNo-Semiスタイルが導入されてきたんだろうけれど、そんな気軽に選択していいスタイルじゃないと思う。
処理の区切りで絶対書き間違いがあるから想像も出来ないけど、tsで20%も採用しているのは驚き。
今時のプロジェクトは Git を使ってますね
そしてセミコロンのあるコードは Git との相性が悪いです
no-semi は true であるべきで trailing-comma も同様に all の方が良いですし
ファイルの末尾には改行が入っているべきです
個人的にはセミコロン無しでの意図しないコードの検出は TypeScript よりも Prettier のようなフォーマッタの貢献が大きいと思います
たとえば下記のようなコードはフォーマッタをかければ明らかに意図しないコードになって気づけるか、あるいは正しく修正されます
私が知る限りでもセミコロン要らない派の意見はどれも古いプロジェクトでしか役に立たないものばかりに感じますし
セミコロンを入れていたためにおこるバグもありますね…
セミコロンは多くのプログラマの時間を無駄にしキーボードの寿命を奪ってきた悪魔だと思っています
我が流派では不要な所(改行削除しても影響皆無)だけ積極的に省略