こんにちは!
TypeScriptで開発を進めていると、「値がない」状態を表すnullとundefinedの違いに戸惑うことはありませんか。どちらも似たような意味に思えますが、実は明確な使い分けが存在します。
プログラミング初心者の方にとって、この2つの「何もない」値の違いを理解することは、バグのない堅牢なコードを書くための第一歩です。
この記事では、TypeScriptにおけるnullとundefinedの決定的な違いと、それぞれの適切な使用シーンについて、初心者の方にも分かりやすく丁寧に解説します。
この記事は次のような方におすすめです。
- TypeScriptを学習中で
nullとundefinedの扱いに迷っている方 - 予期せぬエラー(「Cannot read property…」など)を減らしたい方
- コードの品質を高めるための正しい型定義を知りたい方
strictNullChecksオプションの重要性を理解したい方- チーム開発で共通の認識を持ちたいエンジニアの方
この記事を読めば、nullとundefinedの本質的な違いがクリアになり、自信を持ってコードに記述できるようになります。曖昧な理解を卒業して、より安全で読みやすいTypeScriptコードを書けるようになりましょう。
「なんとなく使っていた」状態から脱却したい方は、ぜひ最後までお付き合いください。
それでは、順を追って詳しく見ていきましょう!
nullとundefinedの基本的な定義
まずはじめに、nullとundefinedがそれぞれどのような意味を持つのか、その基本的な定義から確認していきましょう。これらはどちらも「値が存在しない」ことを示しますが、その「存在しない理由」や「背景」が異なります。
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では、nullとundefinedはそれぞれ独立した型として存在します。これらをどのように扱うかは、tsconfig.jsonの設定にあるstrictNullChecksオプションによって大きく変わります。
strictNullChecksが無効(false)の場合
この設定が無効になっている場合、nullとundefinedはあらゆる型のサブタイプとして扱われます。つまり、number型やstring型の変数に、nullやundefinedを代入できてしまいます。
// strictNullChecks: false の場合
let price: number;
price = 1000; // OK
price = null; // OK(エラーにならない)
price = undefined; // OK(エラーにならない)
これは一見便利に見えるかもしれませんが、実行時に「値があると思っていたのにnullだった」というエラー(いわゆるぬるぽ)を引き起こす大きな原因となります。
strictNullChecksが有効(true)の場合
現代のTypeScript開発では、この設定を有効にすることが強く推奨されています。有効にすると、nullとundefinedは他の型に代入できなくなります。
// strictNullChecks: true の場合
let price: number;
price = 1000; // OK
// price = null; // エラー! number型にnullは代入できません
// price = undefined; // エラー! number型にundefinedは代入できません
もしnullやundefinedを許容したい場合は、ユニオン型を使って明示的に宣言する必要があります。
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入門
プロ開発者への近道!基礎から応用まで幅広くカバー
1一番のおすすめは「プロを目指す人のためのTypeScript入門」です。
この本は、TypeScriptの基礎から高度な使い方まで幅広く解説しています。
初心者でも理解しやすい説明から始まり、徐々に難易度を上げていく構成が特徴。
プログラミング経験者なら、さらに深い理解が得られるでしょう。
実際の開発現場で使えるテクニックも豊富に紹介されているのがポイント。
型の使い方や設計パターンなど、実践的な内容が満載です。
プロの開発者を目指す人はもちろん、TypeScriptをしっかり学びたい人におすすめの一冊。
基礎固めから応用力の向上まで、幅広いニーズに応えてくれます。
現場で使えるTypeScript 詳解実践ガイド
実践的スキルを身につけたい人必見!現場のノウハウが詰まった一冊
次におすすめは「現場で使えるTypeScript 詳解実践ガイド」がランクイン。
この本の特徴は、実際の開発現場で役立つ知識が詰まっていること。
TypeScriptの基本的な文法から始まり、実際のプロジェクトでどう活用するかまで丁寧に解説しています。
エラー対処法や性能改善のコツなど、現場ならではの知恵も満載。
特に、大規模なプロジェクトでTypeScriptを使う際のベストプラクティスが学べるのが魅力。
コードの保守性や再利用性を高める方法も詳しく紹介されています。
すでにJavaScriptの経験がある人や、実務でTypeScriptを使いたい人におすすめ。
この本を読めば、現場で即戦力として活躍できる力が身につくはずです。
書籍に関してはこちらの記事も参考にしてくださいね!
オンラインで参照できる公式ドキュメント
TypeScript公式ハンドブック
https://www.typescriptlang.org/docs/
TypeScriptの公式ドキュメントです。
intersection型を含む、すべての型システムの機能について詳細な説明があります。
TypeScript Deep Dive
https://basarat.gitbook.io/typescript/
TypeScriptの深い部分まで掘り下げて解説しているオンラインブックです。
無料で読むことができ、intersection型についても詳しく説明されています。
TypeScriptの学習は終わりがありません。
新しい機能が常に追加され、より良い書き方が発見されています。
継続的に学習を続けることで、より良いTypeScriptプログラマーになれるはずです。
ひとつひとつ真摯に向き合う企業
株式会社 ONE WEDGEでは、新たな仲間を募集しています!
私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。
- 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
- 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇、有給6日取得で特別休暇付与)を完備!
- 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
- 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
- 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
- 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
- ワークライフバランスを重視し、副業もOK!
株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!
ホームページ、採用情報は下記ボタンからご確認ください!
応募、ご質問など、お問い合わせフォーム、またはX (旧Twitter)、InstagramのDMでお気軽にご相談ください♪
まとめ
今回は、TypeScriptにおけるnullとundefinedの違いについて詳しく解説しました。
undefinedは変数が未定義であることや値がまだない状態を指します。nullは開発者が意図的に値がないことを示すために使います。strictNullChecksを有効にすることで、これらを安全に扱うことができます。- 基本的には
undefinedを使い、外部データ連携などで必要な場合にnullを使うのが一般的です。 - チーム内で明確なルールを定めて運用することが大切です。
一見些細な違いに見えるかもしれませんが、この2つを正しく理解し使い分けることは、TypeScriptの型システムを最大限に活かすために不可欠です。ぜひ、今日からのコーディングで意識してみてください。
※本記事の本文案はAIを活用して作成していますが、記載しているコードは筆者が実際に実行・検証し、内容の正確性を確認したうえで公開しています。


