こんにちは!

TypeScriptで開発を進めていると、「値がない」状態を表すnullundefinedの違いに戸惑うことはありませんか。どちらも似たような意味に思えますが、実は明確な使い分けが存在します。

nullとundefinedって、結局どう使い分ければいいの?
エラーログでundefinedをよく見るけど、nullとの違いが曖昧だわ。
TypeScriptの推奨設定では、これらをどう扱うべきなのかな。

プログラミング初心者の方にとって、この2つの「何もない」値の違いを理解することは、バグのない堅牢なコードを書くための第一歩です。

この記事では、TypeScriptにおけるnullundefinedの決定的な違いと、それぞれの適切な使用シーンについて、初心者の方にも分かりやすく丁寧に解説します。

この記事は次のような方におすすめです。

この記事はこんな人におすすめ!
  • TypeScriptを学習中でnullundefinedの扱いに迷っている方
  • 予期せぬエラー(「Cannot read property…」など)を減らしたい方
  • コードの品質を高めるための正しい型定義を知りたい方
  • strictNullChecksオプションの重要性を理解したい方
  • チーム開発で共通の認識を持ちたいエンジニアの方

この記事を読めば、nullundefinedの本質的な違いがクリアになり、自信を持ってコードに記述できるようになります。曖昧な理解を卒業して、より安全で読みやすいTypeScriptコードを書けるようになりましょう。

「なんとなく使っていた」状態から脱却したい方は、ぜひ最後までお付き合いください。

それでは、順を追って詳しく見ていきましょう!

nullとundefinedの基本的な定義

まずはじめに、nullundefinedがそれぞれどのような意味を持つのか、その基本的な定義から確認していきましょう。これらはどちらも「値が存在しない」ことを示しますが、その「存在しない理由」や「背景」が異なります。

undefined:値が「まだ」ない

undefinedは、変数が宣言されたものの、まだ値が代入されていない状態を表します。つまり、システムやJavaScriptエンジンが自動的に割り当てる「初期状態としての不在」です。

例えば、以下のようなケースでundefinedが発生します。

  • 変数をletで宣言したが、初期値を設定していない場合。
  • オブジェクトに存在しないプロパティへアクセスした場合。
  • 関数が値を返さない(return文がない)場合の戻り値。
  • 関数の引数が渡されなかった場合。

これらはすべて、「値がまだ定義されていない」あるいは「値が見つからない」という自然な状態を示しています。

null:値が「意図的に」ない

一方でnullは、開発者が意図的に「ここには値がない」ということを示したい場合に使用します。システムが勝手にnullを入れることは基本的にはありません。

例えば、以下のようなケースでnullを使います。

  • 検索処理の結果、該当するデータが見つからなかった場合。
  • ユーザーの入力が任意項目であり、入力されなかった場合。
  • オブジェクトのプロパティを意図的にリセットしたい場合。

つまり、nullは「空っぽであること」を明示的に表現するための値だと言えます。

コードで見る具体的な違い

言葉での説明だけではイメージしづらいかもしれませんので、実際のコードを見ながらその違いを確認してみましょう。

undefinedが発生する例

まずは、undefinedが自然に発生する状況を見てみます。

// 1. 変数を宣言しただけの場合
let count: number;
console.log(count); // 出力: undefined

// 2. オブジェクトの存在しないプロパティ
const user = { name: "田中" };
// @ts-ignore
console.log(user.age); // 出力: undefined

// 3. 引数が渡されなかった場合
function greet(name?: string) {
  console.log(name);
}
greet(); // 出力: undefined

このように、undefinedは「何かが欠けている」状態をシステムが教えてくれていると言えます。

「1. 変数を宣言しただけの場合」がエラーになる場合はtsconfig.jsonの設定にあるstrictNullChecksオプションがtrueになっているかデフォルト設定になっている可能性があります。詳しくは「strictNullChecksが有効(true)の場合」の見出しを参考にしてください。

nullを使用する例

次に、nullを使って「値がない」ことを表現する例です。

// ユーザーをIDで検索する関数
function findUser(id: number): string | null {
  if (id === 1) {
    return "田中";
  }
  // 該当するユーザーがいないことを明示的に示す
  return null;
}

const user1 = findUser(1); // "田中"
const user2 = findUser(99); // null

ここでは、findUser関数がユーザーを見つけられなかった場合に、undefinedではなくnullを返しています。これにより、呼び出し元は「エラーで値がない(undefined)」のか、「検索結果として値がなかった(null)」のかを区別しやすくなる場合があります。

TypeScriptにおける型の扱い

TypeScriptでは、nullundefinedはそれぞれ独立した型として存在します。これらをどのように扱うかは、tsconfig.jsonの設定にあるstrictNullChecksオプションによって大きく変わります。

strictNullChecksが無効(false)の場合

この設定が無効になっている場合、nullundefinedはあらゆる型のサブタイプとして扱われます。つまり、number型やstring型の変数に、nullundefinedを代入できてしまいます。

// strictNullChecks: false の場合
let price: number;
price = 1000;      // OK
price = null;      // OK(エラーにならない)
price = undefined; // OK(エラーにならない)

これは一見便利に見えるかもしれませんが、実行時に「値があると思っていたのにnullだった」というエラー(いわゆるぬるぽ)を引き起こす大きな原因となります。

strictNullChecksが有効(true)の場合

現代のTypeScript開発では、この設定を有効にすることが強く推奨されています。有効にすると、nullundefinedは他の型に代入できなくなります。

// strictNullChecks: true の場合
let price: number;
price = 1000;      // OK
// price = null;      // エラー! number型にnullは代入できません
// price = undefined; // エラー! number型にundefinedは代入できません

もしnullundefinedを許容したい場合は、ユニオン型を使って明示的に宣言する必要があります。

let price: number | null;
price = 1000; // OK
price = null; // OK

このように厳格に管理することで、意図しない「値がない状態」によるバグを未然に防ぐことができます。

実践的な使い分けの指針

では、実際の開発現場ではこれらをどのように使い分ければよいのでしょうか。いくつかの一般的な指針をご紹介します。

基本はundefinedを使用する

TypeScriptチームや多くのスタイルガイドでは、可能な限りundefinedを使用することを推奨しています。理由はシンプルで、JavaScript自体がデフォルト値としてundefinedを使用するため、それに合わせる方が自然だからです。

特に、関数のオプション引数や、オブジェクトの省略可能なプロパティは、自動的にundefinedとして扱われます。あえてnullを使おうとすると、string | null | undefinedのような複雑な型定義が必要になってしまうことがあります。

nullは「値の不在」をデータとして扱う場合に使う

一方で、APIのレスポンスやデータベースの値として「値が設定されていないこと」自体に意味がある場合は、nullが適しています。JSON形式ではundefinedは扱えず、値がない場合はnullで表現されるのが一般的だからです。

また、変数の値を「リセット」したい場合にもnullが使われることがあります。undefinedを代入すると「初期化忘れ」と区別がつかなくなる恐れがあるため、意図的に空にしたことを示すためにnullを使うという考え方です。

チーム内でルールを決めることが最重要

最も重要なのは、プロジェクトやチーム内で統一されたルールを持つことです。「変数の初期化にはundefinedを使う」「APIの戻り値以外ではnullを使わない」といったルールを決めておくことで、コードの一貫性が保たれ、無用な混乱を避けることができます。

【付録】さらに学びを深めるためのリソース


さらにTypescriptの学習を進めたい方のために、いくつかのリソースを紹介します。
これらのリソースを活用することで、TypeScriptの型システムについてより深い知識を得ることができるでしょう。

おすすめの書籍

ゼロからわかる TypeScript入門


技術評論社から出版されている「ゼロからわかる TypeScript入門」は、プログラミング初心者や本職プログラマーではない方を主な対象にした入門書です。

変数・条件分岐・ループといった基本から、クラスやインターフェース、モジュールまで段階的に学べる構成になっています。最終章ではWeb APIとJSONを使った非同期Webアプリの作成も体験できるので、「実際に動くものを作る」ところまで到達できます。

プロを目指す人のためのTypeScript入門


技術評論社の「プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで」、通称 ブルーベリー本 です。
JavaScriptの仕様とTypeScript独自の機能を両方押さえつつ、リテラル型・ユニオン型・keyof型・ジェネリクスなど、高度な型表現まで踏み込んで解説しています。TypeScriptの型システムの表現力を本格的に学べる一冊です。

オンラインで参照できる公式ドキュメント

TypeScript公式ハンドブック


https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。

TypeScript Deep Dive


https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。

TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。


キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇、有給6日取得で特別休暇付与)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、お問い合わせフォーム、またはX (旧Twitter)、InstagramのDMでお気軽にご相談ください♪

まとめ

今回は、TypeScriptにおけるnullundefinedの違いについて詳しく解説しました。

  • undefinedは変数が未定義であることや値がまだない状態を指します。
  • nullは開発者が意図的に値がないことを示すために使います。
  • strictNullChecksを有効にすることで、これらを安全に扱うことができます。
  • 基本的にはundefinedを使い、外部データ連携などで必要な場合にnullを使うのが一般的です。
  • チーム内で明確なルールを定めて運用することが大切です。

一見些細な違いに見えるかもしれませんが、この2つを正しく理解し使い分けることは、TypeScriptの型システムを最大限に活かすために不可欠です。ぜひ、今日からのコーディングで意識してみてください。

※本記事の本文案はAIを活用して作成していますが、記載している内容およびコードは筆者が実際に調査、検証・実行し、内容の正確性を確認した上で公開しています。