みなさんこんにちは!ヒロポンです!
C# 育ちの人が TypeScript を始めて、最初に「うっ」となるのが tsconfig.json じゃないですか??
tsc --init で作ると、コメント付きで設定項目が100個くらいズラッと並ぶ。
C# の .csproj はもっと素っ気ないので、この量にまず怯む。「で、結局どれ入れればいいの?」ってなるやつです。
俺も TS を触り始めた頃、この tsconfig を頭から全部読もうとして、早々に力尽きました。
先に結論を言っておく。C# 出身者はまず strict を true にする。ぶっちゃけ、これだけで大枠 OK です。
今回はその strict と、中でも一番効く strictNullChecks(C# 8 の Nullable 参照型に相当するやつ)を軸に、tsconfig を C# 感覚でどこから触るかを段階で組み立てていきます。
tsconfig の strict を C# の型安全さに寄せておくと、TS でも「C# っぽい安心感」で書けるようになる。そこがゴールです。
忙しい人向けに最初にまとめ
- 新規なら
"strict": trueをまず入れる。複数の厳格チェックを一括で on にするスイッチ - その中の
strictNullChecksが C# 8 の Nullable 参照型(#nullable enable)に相当。null / undefined を型で追跡してくれる - 後から strict を有効にすると既存コードが大量にエラーになる。だから最初から入れる
- 他に最低限効かせるのは
target(出力する JS バージョン)、module、esModuleInterop(default import を素直にする) - 既存プロジェクトへの後入れは、
noImplicitAny→strictNullChecksと1つずつ上げる
完成形の tsconfig は Step 5 に丸ごと置いてます。まず、何ができるようになるかから。
完成イメージ — C# の型安全さを TypeScript でも効かせる
ゴールはシンプルです。「C# で当たり前にやってた型の守り」を TypeScript でも効かせること。
C# だと、string に null を代入したら、Nullable 参照型を有効にしていれば警告が出ますよね。
TypeScript も、設定次第で同じことができる。
逆に言うと、設定しないと null チェックが一切効かないゆるい言語にもなる。え、そんなにゆるいの??って感じですが、そこは設定次第なんです。
その分かれ目が tsconfig.json の strict 系オプション。ここを最初に締めておけば、「C# なら弾いてくれたのに TS だと素通りして、本番で undefined エラー」みたいな事故が、コンパイル時に止まります。
ここまでで分かったこと: tsconfig の strict 系を入れると、C# の Nullable 参照型に近い「null を型で守る」状態を TypeScript でも作れる。
前提 — tsc か bun が入っていること
TypeScript をコンパイルできる環境があれば OK です。
npm install -g typescript で tsc を入れるか、bun を使うなら bunx tsc で動く。この記事のコードは、その tsc に相当するコンパイラで型チェックする前提です。
Step 1: tsc –init で tsconfig.json を作る
まず設定ファイルの雛形を生成します。
# プロジェクトのルートで実行
tsc --init
これで、コメントびっしりの tsconfig.json ができます。
C# 出身者はここで全部読もうとしないこと。触るのは数個でいいので、順に足していきます。
Step 2: まず strict を true にする
いちばん大事な1行がこれ。
{
"compilerOptions": {
"strict": true
}
}
strict は単独のチェックじゃなくて、複数の厳格フラグを一括で有効にするスイッチです。strictNullChecks や noImplicitAny(型注釈のない暗黙の any を禁止)みたいな、型を厳しく見る設定がまとめて on になります。
C# で言えば、警告レベルを上げて「怪しい書き方を全部つつく」状態に近い。
最初はうるさく感じます。けど、これが TypeScript を「型のある言語」として使うための土台なんですよね。
ここまでで分かったこと:
strict: trueは複数の厳格チェックをまとめて有効にするスイッチ。TS を型安全に使う土台になる。
Step 3: strictNullChecks は C# 8 の Nullable 参照型に相当する
strict の中でも、C# 出身者に一番効くのが strictNullChecks です。
これを有効にすると、null と undefined は、他の型に勝手に代入できなくなる。
試しに、string に null を入れてみます。
// strictNullChecks が有効だとこれはエラーになる
let userName: string = null;
// error TS2322: Type 'null' is not assignable to type 'string'.
実行結果(型チェック):

string 型に null は入らない、と怒られました!! これ、C# 8 の Nullable 参照型とまったく同じ発想です。
C# で string name に null を入れると警告が出て、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# の.csprojのTargetFramework(net8.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 の項目が急に迷子じゃなくなります。
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# の bin と obj を分ける感覚に近い。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 を土台にする
- 既存プロジェクトへの後入れは大量エラー。
noImplicitAny→strictNullChecksと1つずつ
tsconfig は項目が多くて身構えるけど、C# 出身者が最初に握るのは実質 strict まわりだけ。こんな感じでここを締めておけば、TypeScript でも C# で慣れた「型が守ってくれる感覚」で書けます。そして TypeScript を1つ足せると、任せてもらえる案件の幅が地味に広がる。そこがこの設定を最初に固めておく一番の効きどころです。
よくある質問
strict を true にすると、どの厳格フラグが有効になりますか
strictNullChecks、noImplicitAny、strictFunctionTypes、strictBindCallApply、strictPropertyInitialization、noImplicitThis、alwaysStrict など、型を厳しく見るための複数のフラグがまとめて有効になります(含まれるフラグは 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 で経歴詳細を見る



