TypeScript

TypeScriptのセミコロンは必要か|省略の判断とESLint・Prettier設定【2026年版】

TypeScriptもJavaScriptも、文末のセミコロンは大半の行で省略できます。省略できないのは、自動セミコロン挿入(ASI)が働かない一部の行だけです。問題は「省略できるか」ではなく、その一部をチームの誰が検出するか。ここが決まっていないうちにセミコロンを外すと、レビューで拾えないバグを抱え込みます。ASIの規則、壊れる具体例、ESLint・Prettier・Biomeの設定、そして省略を選ぶべきでない条件を、2026年7月時点の各ツールの実装にもとづいて整理します。

まとめ:既定は「付ける」、外すならフォーマッタの強制とセットで

判断の要点は4つです。

  • セミコロンの有無は型検査の結果を変えません。変わるのは構文解析の段階で、ASIがどこを文の切れ目と見なすかです。
  • ASIは3つの規則で切れ目を補いますが、行頭が ( [ ` + - / の行と、return 直後の改行は救いません。
  • ESLintの semi ルールは v8.53.0 で非推奨になり、v11.0.0 での削除が予告されています。いま書くなら @stylistic/semi です。@typescript-eslint/semi は v8 系で同梱されなくなりました。
  • Prettierの semi は既定 truefalse にすると危険な行の先頭にだけセミコロンを残しますが、すでに連結して書かれたコードは直しません。Biomeの semicolons も既定は "always" です。

裏返すと、フォーマッタをCIで強制していないチームがセミコロンを外す理由はありません。以下、規則と設定を順に見ていきます。

自動セミコロン挿入(ASI)が省略を成立させる3つの規則

セミコロンを書かないコードが動くのは、パーサーが解析中にセミコロンを補うからです。MDNの字句文法が示すとおり、挿入が起きるのは次の3つの場合に限られます。

ASIがセミコロンを補う条件と、補わない条件

1つめは、文法上そこに置けないトークンに出会ったとき。直前のトークンとの間に改行が1つ以上あるか、そのトークンが } であれば、手前にセミコロンが入ります。2つめは、入力の末尾に達してもプログラムとして解釈しきれないとき。3つめは、改行が文法で禁止されている位置に改行が現れたときです。

3つめが指す「改行が禁止された位置」は仕様で列挙されています。return throw break continue yield の直後、インクリメント・デクリメント演算子の手前、アロー関数の => の手前、async function の間などです。ここに改行を入れると、意図とは無関係にその位置で文が終わります。

行頭が ( や [ の行で式が連結される例

逆に言えば、1つめの規則は「次の行と繋げても文法的に成立してしまう」場合には働きません。行頭が ([ の行が典型です。

const a = 1
(1).toString()
// a = 1(1).toString() と解釈され、1 を関数として呼ぶTypeErrorになる

const b = 1
[1, 2, 3].forEach(console.log)
// b = 1[1, 2, 3].forEach(console.log) と解釈される
// 角括弧の中はカンマ演算子で 3 に評価され、1[3] は undefined
// TypeError: Cannot read properties of undefined (reading 'forEach')

同じことが、テンプレートリテラルの `、単項の + -、正規表現リテラルの / で始まる行にも起きます。No-Semiスタイルで書かれたコードの行頭にセミコロンが単独で置かれているのは、この連結を切るためです。

return の直後で改行して undefined が返る例

function build() {
  return
    { ok: true }
}

build() // undefined

return は改行が禁止された位置なので、ASIが return; として文を閉じます。オブジェクトリテラルは到達しないコードになり、しかも構文エラーは出ません。セミコロンを書く流儀でもこの罠は同じで、セミコロンの有無ではなく改行位置の問題です。

TypeScript側でセミコロンが意味を持つ箇所

TypeScriptのコンパイラはJavaScriptと同じASI規則で構文解析します。最新の 7.0.2(2026年7月8日公開)でも前提は変わりません。型注釈やジェネリクスがセミコロンの要否を変えることはなく、上のASIの罠がそのまま当てはまります。

ただしTypeScript固有の構文には、セミコロンが区切り文字として意味を持つ場所があります。代表が interface のメンバー区切りで、;, と改行のいずれも構文上は有効です。どれに揃えるかは @stylistic/member-delimiter-style が担当し、文末の @stylistic/semi とは別ルールになっています。クラスのプロパティ宣言や declare 文も文として扱われ、省略した場合はASIに依存します。型定義ファイルを手書きするなら、この区切りだけは明示したほうが差分レビューが読みやすくなるはずです。

ESLintでセミコロンを強制する現在の書き方

非推奨になった core の semi ルールと使用期限

ESLint公式のルールページには「このルールは ESLint v8.53.0 で非推奨になりました。v11.0.0 で削除されます。@stylistic/eslint-plugin の対応するルールを使ってください」と明記されています。ESLint本体の最新は 10.8.0 なので、core の semi は現時点でも動きます。動きはしますが、バグ修正も機能追加も行われません。既存プロジェクトで semi を設定したままなら、v11の前に移行しておく作業が確定していると考えてください。

@stylistic/semi へ書き換えるflat config

// eslint.config.js
import stylistic from '@stylistic/eslint-plugin'

export default [
  {
    plugins: { '@stylistic': stylistic },
    rules: {
      '@stylistic/semi': ['error', 'always'],
    },
  },
]

省略する規約なら第2引数を 'never' にします。このとき指定できるのが beforeStatementContinuationChars で、既定の 'any' は行頭が [ ( / + - の行の手前にあるセミコロンを見逃し、'always' はその位置のセミコロンを必須として検査します。

'@stylistic/semi': ['error', 'never', { beforeStatementContinuationChars: 'always' }]

ただし、このオプションを入れても前節の連結そのものは止まりません。効くのはASIがすでに文を分けている位置(直前が } や import 文など)だけで、const a = 1 の次行に [1, 2].forEach(...) と書いたコードは1つの文として解析されるため、セミコロンの欠落自体が存在しないからです。対象文字も [ ( / + - の5つで、テンプレートリテラルのバックティックは含みません。書式の統一までが @stylistic/semi の役割だと切り分けてください。

連結そのものを検出する no-unexpected-multiline

行の連結を機械的に拾うのは、ESLint core の no-unexpected-multiline(紛らわしい複数行式の禁止)です。書式系ではないため非推奨の対象になっておらず、@eslint/js の recommended 設定に最初から含まれています。No-Semiを採用するチームが本当に入れるべきなのはこちらで、前節の3パターンをそれぞれ別のメッセージで指摘します。

2:1 Unexpected newline between function and ( of function call
4:1 Unexpected newline between object and [ of property access
6:1 Unexpected newline between template tag and template literal

recommended を継承していないflat configでは自前で有効化が必要です。セミコロン省略を許すなら、@stylistic/semi'never' とこのルールを必ずセットで設定してください。

@stylistic/eslint-plugin の最新は 5.10.0 です。v4以降はESMのみの配布に変わり、flat config と ESLint v9 以上が前提になりました。.eslintrc を使い続けているプロジェクトは、3.x を挟むか flat config へ移ってから導入することになります。ESLint本体の設定やPrettierとの連携はESLintとは?VSCodeでの設定からflat config・Prettier連携まで解説【ESLint v10対応】で扱っています。

@typescript-eslint/semi が解決できないときの対処

Definition for rule '@typescript-eslint/semi' was not found というエラーは、プラグインをv8系へ上げたときに出ます。@typescript-eslint/eslint-plugin は 7.18.0 まで semi ルールを同梱していましたが、8.65.0 の配布物にはルールファイルそのものがありません。書式系のルールはすべて ESLint Stylistic へ移されました。

置き換え先は @stylistic/semi の一択です。かつてはTypeScript向けの派生を @stylistic/eslint-plugin-ts(ルール名 @stylistic/ts/semi)が担っていましたが、このサブパッケージは 4.4.1(2025年6月4日)で更新が止まり、本体のv5系ではTS構文の扱いが @stylistic/semi に統合されました。5.10.0 の配布物が持つルールは97件すべてが接頭辞なしの平坦な名前空間で、ts/ は1件もありません。ここで @stylistic/ts/semi と書くと could not find plugin "@stylistic/ts" になり、直そうとしたエラーを別の形で再発させます。移行時に @typescript-eslint/semi の設定行を消し忘れてもルール未定義でリント全体が落ちるので、CIが赤くなったらまず設定ファイルを grep してください。

PrettierとBiomeでの設定と、ESLintとの二重管理の回避

Prettierのsemiオプションと行頭セミコロンの自動付与

Prettier 3.9.6 の semi は既定 true。公式のオプション一覧は false の挙動を「ASI failure を招きうる行の先頭にのみセミコロンを付ける」と説明しています。

// .prettierrc.json
{ "semi": false }

効くのは、セミコロンありで書かれたコードから外す経路です。入力と出力を並べると範囲がはっきりします。

// 入力(セミコロンありで書いたコード)
const a = 1;
[1, 2, 3].forEach(console.log);

// prettier --no-semi の出力
const a = 1
;[1, 2, 3].forEach(console.log)

一方、最初からセミコロン無しで const a = 1 の次行に [1, 2, 3].forEach(...) と書かれたコードは、Prettierが読む時点で1つの文です。整形しても解釈は戻らず、連結されたまま出力されます。手書きの連結まで潰したいなら、前述の no-unexpected-multiline を併用してください。Prettier自体の導入手順はPrettierとは?意味・読み方からコマンド・設定・ESLintとの違いまでにまとめています。

Biomeのsemicolons設定と既定値

Biome 2.5.5 では、同じ設定が javascript.formatter.semicolons にあります。設定スキーマ上の値は "always""asNeeded" の2つで、既定は "always" です。

{
  "javascript": {
    "formatter": { "semicolons": "asNeeded" }
  }
}

"asNeeded" はPrettierの semi: false に対応し、必要な行にだけセミコロンを残します。Rust製ツールチェーンへの移行を検討しているならOxcとは?Rust製の高速JavaScript/TypeScriptツールチェーン|Oxlintの使い方とESLint比較Oxlintとは?読み方・使い方とESLint・Biomeとの違いを解説も参考になります。

フォーマッタとリンタで設定が競合したときの整理

ツール 最新版 設定名 既定 省略する値
ESLint Stylistic 5.10.0 @stylistic/semi 既定では無効 ‘never’
Prettier 3.9.6 semi true false
Biome 2.5.5 semicolons “always” “asNeeded”

ESLintとPrettierを併用すると、@stylistic/semisemi オプションが逆向きに設定されたときにリントと整形が無限に打ち消し合います。書式判断をPrettierへ寄せるなら eslint-config-prettier(10.1.8)を設定の最後に置き、競合するルールを無効化してください。セミコロンの真実の設定値を1ファイルに集約しておくのが、事故を防ぐ最短の方法です。

セミコロンを省略すべきでないチームの条件

好みの問題として語られがちですが、省略が破綻する条件ははっきりしています。次のいずれかに当てはまるなら、No-Semiは選ばないほうがいい判断です。

  • 整形がローカルの保存時フックだけで、CIにフォーマットチェックが無い。設定を入れ忘れた開発者のコミットが素通りします。
  • 外部から持ち込んだコード片の貼り付けが多い。行頭が ([ のスニペットを既存行の直後に貼ると、その場では気づけません。
  • ビルド前にコード生成やテンプレート結合で行を連結する処理がある。生成側はASIを考慮しません。
  • 参照している規約が更新されていない。eslint-config-airbnb は 19.0.4 が 2021年12月25日公開のまま止まっており、「Airbnbに合わせる」という判断はもはや現行のツール構成の裏付けになりません。セミコロン省略側の standard も 17.1.2(2024年9月13日)が最新です。

逆に、Prettier または Biome をCIで強制していて、規約をリポジトリの設定ファイルで管理しているなら、どちらを選んでも実務上の差はほとんど出ません。その場合に優先すべきはチーム内の統一で、既存プロジェクトの流儀を途中で反転させる価値はありません。全ファイルが書き換わって以降の git blame が読めなくなるコストのほうが、可読性の改善より大きいからです。方針を変えるなら、リポジトリを分ける区切りか、大規模改修と同じコミットに合わせてください。リンタ・フォーマッタを含むツール全体の位置づけは静的解析とは何か?ソースコードを実行せずに品質を確保する手法で整理しています。

よくある質問

TypeScriptでセミコロンを省略すると動作は変わりますか?

大半の行では変わりません。型検査の結果にも、生成されるJavaScriptの意味にも影響しません。変わるのは、ASIが文の切れ目をどこに置くかです。行頭が ( [ ` + - / の行は直前の行と連結され、return の直後で改行した場合は undefined が返ります。この2パターンだけが実害のある差分です。前者はセミコロンありのコードを semi: false で外す限りフォーマッタが行頭にセミコロンを補いますが、後者は整形では直りません。return と次行の間の改行はPrettierも残すため、undefined が返る挙動は変わらず、検出はESLintの no-unreachable が担います。

ESLintのsemiルールはまだ使えますか?

使えますが、非推奨です。ESLint v8.53.0 で非推奨となり、v11.0.0 での削除が公式に予告されています。本体の最新は 10.8.0 なので、いま動いている設定がすぐ壊れるわけではありません。ただし今後の修正は入らないため、新規に書くなら @stylistic/semi、既存プロジェクトはv11の到来前に置き換えておくのが妥当です。

Prettierでセミコロンを消すにはどう設定しますか?

設定ファイルに { "semi": false } を追加します。既定は true です。false でも、Prettierは前の行と連結されうる行の先頭にセミコロンを付けるため、整形後のコードがASIで壊れることはありません。Biomeを使っている場合は javascript.formatter.semicolons"asNeeded" にします。

JavaScriptでセミコロンが不要なのはどんな行ですか?

次の行が新しい文として解釈できる限り、ほぼすべての文で不要です。逆に必要なのは、次の行が前の行の続きとして解釈できてしまう場合だけです。判定を暗記する必要はありません。書式の統一は @stylistic/semi'never'、連結してしまった行の検出は no-unexpected-multiline と役割が分かれているので、両方を有効にすれば危険な位置だけがリンタから指摘されます。

@typescript-eslint/semi が見つからないと出るのはなぜですか?

@typescript-eslint/eslint-plugin のv8系で、このルールが同梱されなくなったためです。7.18.0 の配布物には semi のルールファイルがありますが、8.65.0 にはありません。書式系ルールがESLint Stylisticへ移管されたことによるもので、設定を @stylistic/semi へ書き換えれば解消します。@stylistic/ts/semi は現行の 5.10.0 に存在しないため、こちらへ書き換えると同じ「plugin が見つからない」エラーになります。

関連記事

資料請求

RELATED POSTS 関連記事