動くコード図鑑技術記事現場の渡り方キャリア論すべての記事About
技術記事

C# 出身者のための tsconfig.json 最初の設定(strict と strictNullChecks から)

バイブス父さん
現役の業務SE
2026年9月10日15 min read広告 (PR) を含む場合があります
C# 出身者のための tsconfig.json 最初の設定(strict と strictNullChecks から)

みなさんこんにちは!ヒロポンです!

C# 育ちの人が TypeScript を始めて、最初に「うっ」となるのが tsconfig.json じゃないですか??

tsc --init で作ると、コメント付きで設定項目が100個くらいズラッと並ぶ。

C# の .csproj はもっと素っ気ないので、この量にまず怯む。「で、結局どれ入れればいいの?」ってなるやつです。

俺も TS を触り始めた頃、この tsconfig を頭から全部読もうとして、早々に力尽きました。

先に結論を言っておく。C# 出身者はまず stricttrue にする。ぶっちゃけ、これだけで大枠 OK です。

今回はその strict と、中でも一番効く strictNullChecks(C# 8 の Nullable 参照型に相当するやつ)を軸に、tsconfig を C# 感覚でどこから触るかを段階で組み立てていきます。

tsconfigstrict を C# の型安全さに寄せておくと、TS でも「C# っぽい安心感」で書けるようになる。そこがゴールです。

忙しい人向けに最初にまとめ

  • 新規なら "strict": true をまず入れる。複数の厳格チェックを一括で on にするスイッチ
  • その中の strictNullChecksC# 8 の Nullable 参照型(#nullable enable)に相当。null / undefined を型で追跡してくれる
  • 後から strict を有効にすると既存コードが大量にエラーになる。だから最初から入れる
  • 他に最低限効かせるのは target(出力する JS バージョン)moduleesModuleInterop(default import を素直にする)
  • 既存プロジェクトへの後入れは、noImplicitAnystrictNullChecks1つずつ上げる

完成形の tsconfig は Step 5 に丸ごと置いてます。まず、何ができるようになるかから。

完成イメージ — C# の型安全さを TypeScript でも効かせる

ゴールはシンプルです。「C# で当たり前にやってた型の守り」を TypeScript でも効かせること。

C# だと、stringnull を代入したら、Nullable 参照型を有効にしていれば警告が出ますよね。

TypeScript も、設定次第で同じことができる。

逆に言うと、設定しないと null チェックが一切効かないゆるい言語にもなる。え、そんなにゆるいの??って感じですが、そこは設定次第なんです。

その分かれ目が tsconfig.jsonstrict 系オプション。ここを最初に締めておけば、「C# なら弾いてくれたのに TS だと素通りして、本番で undefined エラー」みたいな事故が、コンパイル時に止まります。

ここまでで分かったこと: tsconfig の strict 系を入れると、C# の Nullable 参照型に近い「null を型で守る」状態を TypeScript でも作れる。

前提 — tsc か bun が入っていること

TypeScript をコンパイルできる環境があれば OK です。

npm install -g typescripttsc を入れるか、bun を使うなら bunx tsc で動く。この記事のコードは、その tsc に相当するコンパイラで型チェックする前提です。

Step 1: tsc –init で tsconfig.json を作る

まず設定ファイルの雛形を生成します。

# プロジェクトのルートで実行
tsc --init

これで、コメントびっしりの tsconfig.json ができます。

C# 出身者はここで全部読もうとしないこと。触るのは数個でいいので、順に足していきます。

Step 2: まず strict を true にする

いちばん大事な1行がこれ。

{
  "compilerOptions": {
    "strict": true
  }
}

strict単独のチェックじゃなくて、複数の厳格フラグを一括で有効にするスイッチです。strictNullChecksnoImplicitAny(型注釈のない暗黙の any を禁止)みたいな、型を厳しく見る設定がまとめて on になります。

C# で言えば、警告レベルを上げて「怪しい書き方を全部つつく」状態に近い。

最初はうるさく感じます。けど、これが TypeScript を「型のある言語」として使うための土台なんですよね。

ここまでで分かったこと: strict: true は複数の厳格チェックをまとめて有効にするスイッチ。TS を型安全に使う土台になる。

Step 3: strictNullChecks は C# 8 の Nullable 参照型に相当する

strict の中でも、C# 出身者に一番効くのが strictNullChecks です。

これを有効にすると、nullundefined は、他の型に勝手に代入できなくなる

試しに、stringnull を入れてみます。

// strictNullChecks が有効だとこれはエラーになる
let userName: string = null;
// error TS2322: Type 'null' is not assignable to type 'string'.

実行結果(型チェック):

strictNullChecks 有効時に let userName: string = null がコンパイルエラー TS2322 になっている型チェック結果

string 型に null は入らない、と怒られました!! これ、C# 8 の Nullable 参照型とまったく同じ発想です。

C# で string namenull を入れると警告が出て、null を許すなら string? と書く。TypeScript も、null を許すなら型でそう書きます。

// null を許すなら、型に | null を足して明示する
let userName: string | null = null;   // OK

対応させるとこう。

  • C# の string(非 null)↔ TS の string(strictNullChecks 有効)
  • C# の string?(null 許容)↔ TS の string | null

C# で <Nullable>enable</Nullable> を入れるのと、tsconfig で strictNullChecks を入れるのは、ほぼ同じ意味だと思っていい。null の可能性を型で追跡する、という思想が共通してます。

ここまでで分かったこと: strictNullChecks は C# 8 の Nullable 参照型に相当。null を許すなら string | null と型で明示する。

Step 4: target / module / esModuleInterop の意味

型の守りは Step 3 までで固まりました。

あと最低限、出力まわりの3つだけ意味を押さえます。

{
  "compilerOptions": {
    "strict": true,
    "target": "ES2020",
    "module": "commonjs",
    "esModuleInterop": true
  }
}
  • target: どのバージョンの JavaScript を出力するか。C# の .csprojTargetFrameworknet8.0 等)に近い立ち位置。迷ったら ES2020 あたりで足ります
  • module: 出力するモジュール方式。Node.js で動かすなら commonjs、モダンな環境なら ESNext。C# の名前空間・アセンブリ参照の解決方式に相当する、と思うと入りやすい
  • esModuleInterop: true にしておくと、import express from "express" みたいな default import が素直に書けるようになる。付けないと古い形式で書く羽目になるので、実質必須です

ここまでで分かったこと: target は出力 JS バージョン、module はモジュール方式、esModuleInterop は default import を素直にする。この3つは実質定番。

C# の設定と tsconfig の対応(早見表)

ここまで出てきたものを、C# 感覚で対応させると、一枚でこうなります。

C# の設定概念と tsconfig オプションの対応表。Nullable 参照型と strictNullChecks、TargetFramework と target などを何が効くかと並べた早見表

「C# のあれに相当するのはこれ」と紐づけておく。それだけで、tsconfig の項目が急に迷子じゃなくなります。

Step 5: C# 出身者向けの推奨初期設定

こんな感じで、ここまでを1つにまとめた、そのまま使える初期 tsconfig がこれです。新規プロジェクトなら、これをベースに始めれば大きく外しません。

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

outDir / rootDir は、ソース(src)と出力(dist)を分ける指定。C# の binobj を分ける感覚に近い。skipLibCheck は、ライブラリ側の型定義のチェックを省いてコンパイルを速くする、実務的なオプションです。

動作確認 — strictNullChecks が本当に null を弾くか

設定が効いてるかは、わざと null を入れて確かめるのが早いです。

Step 3 の let userName: string = null; を書いたファイルを、strict(または strictNullChecks)を有効にした tsconfig でコンパイルしてみてください。

上の実行結果(block-1)のように error TS2322 が出れば、null の守りが効いています!! 逆に、この行がすんなり通ってしまうなら、strictNullChecks が有効になってない合図。tsconfig を見直してください。

型注釈を string | null に直すと、いい感じにエラーが消えます。この「エラーが出て、型で直すと消える」体験が、C# の Nullable 参照型そのままなんですよね。

こんなエラーが出たら — 既存プロジェクトに後から strict を入れる時

ここがC# 出身者がいちばん詰まるところ。

既存の TypeScript プロジェクトに、あとから strict: true を入れると、エラーが数百件まとめて噴き出すことがあります。え、数百件??ってなるやつです。

これは strict のバグじゃない。「今まで見逃されてた緩い書き方が、一斉に炙り出された」状態です。

とはいえ、数百件を一気には直せない。そこで段階的に有効化します。

  • まず "noImplicitAny": true だけ入れて、暗黙の any を潰す
  • 落ち着いたら "strictNullChecks": true を足して、null まわりを直す
  • そこまで済んだら "strict": true に切り替える(残りの厳格フラグも有効化)

strict: true の代わりに、中身のフラグを1つずつ指定すれば、部分的に先行して締められる。C# で警告を一気に error にせず、段階的に潰していくのと同じ発想です。

だから、新規なら最初から strict、既存なら1つずつ。これが鉄則です。

ここまでで分かったこと: 既存プロジェクトへの strict 後入れは大量エラーになる。noImplicitAny → strictNullChecks と1つずつ上げるのが現実的。

まとめ

C# 出身者が tsconfig.json をどこから触るか、段階で組み立ててきました。

  • 新規なら "strict": true をまず入れる。複数の厳格チェックを一括 on にするスイッチ
  • strictNullChecks は C# 8 の Nullable 参照型に相当。null を許すなら string | null と型で明示
  • 出力まわりは target / module / esModuleInterop の3つを押さえれば実質足りる
  • 完成形は Step 5 の tsconfig を土台にする
  • 既存プロジェクトへの後入れは大量エラーnoImplicitAnystrictNullChecks と1つずつ

tsconfig は項目が多くて身構えるけど、C# 出身者が最初に握るのは実質 strict まわりだけ。こんな感じでここを締めておけば、TypeScript でも C# で慣れた「型が守ってくれる感覚」で書けます。そして TypeScript を1つ足せると、任せてもらえる案件の幅が地味に広がる。そこがこの設定を最初に固めておく一番の効きどころです。

よくある質問

strict を true にすると、どの厳格フラグが有効になりますか

strictNullChecksnoImplicitAnystrictFunctionTypesstrictBindCallApplystrictPropertyInitializationnoImplicitThisalwaysStrict など、型を厳しく見るための複数のフラグがまとめて有効になります(含まれるフラグは TypeScript のバージョンで少しずつ増えます)。個別に上げ下げしたい時は、strict: true を書いたうえで特定のフラグだけ false に戻す、という指定もできます。

target は何を選べばいいですか

動かす実行環境に合わせます。特に事情がなければ ES2020 あたりが無難です。古いブラウザまで面倒を見る必要があるなら ES2015(ES6)まで下げ、モダンな Node.js だけが対象なら ES2022 などに上げてもかまいません。C# の TargetFramework を選ぶ感覚と同じで、出力先に合わせて決めます。

esModuleInterop はいつも入れておくべきですか

実務ではほぼ入れておいて問題ありません。esModuleInterop: true は、CommonJS のモジュールを import express from "express" の形で素直に読み込めるようにする設定です。これが無いと import * as express from "express" のような書き方を強いられ、多くのライブラリのサンプルコードと食い違って混乱します。新規なら最初から入れておくのが楽です。

動作確認メモ

この記事の TypeScript コード(strictNullChecks 有効時に let userName: string = null がエラーになること・string | null に直すと通ること)は、コンテナ上の TypeScript コンパイラで型チェックし、記載のエラー(TS2322)と解消を確認しています。tsconfig の JSON 例は設定内容の提示です。お使いの TypeScript のバージョンによって strict に含まれるフラグが多少増減する点だけ、公式の TSConfig リファレンスで確認してください。

次に読むべき記事

以上!

同じ「tsconfig の項目多すぎて心折れた」経験がある人、どんどんシェア待ってるぜ!!


執筆者

バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SIer の正社員からフリーランスに転じ、 複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る


この記事のコードと手順は ぜんぶ動作検証済み。 安心して現場で試してくれ。
バイブス父さん

現役の業務SE。C# / SQL Server 保守の現場から、コードも人もキャリアも全部書く。 実体験ベース。

運営者について