【入門編】 NonNullableによるnullとundefinedの排除 – TypeScript実践ガイド

こんにちは!TypeScriptの世界へようこそ。チーフアーキテクトの私です。

日々、たくさんのコードを書いていると、「ああっ、また君か!」と頭を抱えたくなるエラーに出会いませんか?そう、JavaScriptやTypeScriptの歴史の中で、おそらく世界中の開発者が一番お世話になり、そして一番悩まされてきたエラー……。

そう、「Cannot read properties of undefined (reading ‘〇〇’)」(undefinedのプロパティを読み込めません)です。

画面が真っ白になったり、コンソールに赤字がずらりと並んだりするあの瞬間、本当に冷や汗が流れますよね。「TypeScriptを使っていれば、型が守ってくれるはずじゃなかったの!?」と叫びたくなる気持ち、痛いほどよく分かります。

でも、安心してください。TypeScriptには、そんな「nullやundefinedの魔物」をピシャリと追い払ってくれる、とっても頼もしい秘密兵器が用意されているんです。それが今回ご紹介する `NonNullable` という型です!

難しく聞こえるかもしれませんが、身近な例えを交えながらゆっくり紐解いていきますので、肩の力を抜いてお付き合いくださいね。

—

1. 「なんでも入れられる箱」の落とし穴

TypeScriptを学び始めると、`string`(文字列)やキスト、`number`(数値)といった基本的な型を覚えますよね。

例えば、ユーザーの名前を管理する変数を考えてみましょう。

let userName: string = “田中さん”;

これなら安心です。「`userName`には絶対に文字列が入る」とTypeScriptが太鼓判を押してくれています。

しかし、実際のWeb開発はそんなに甘くありません。データベースからデータを取ってくるまでの間や、ユーザーがまだ入力していない瞬間など、世の中には「まだ値がない(= undefined)」、あるいは「データが存在しない(= null)」という状態が山ほどあります。

そこで、私たちはついついこんな型定義をしてしまいがちです。

// 文字列かもしれないし、nullやundefinedかもしれない
let inputData: string | null | undefined = “こんにちは”;

この `string | null | undefined` は、いわば「何が入っているか開けてみるまで分からない、開けたら空っぽかもしれないおもちゃ箱」のようなものです。

この箱からデータを取り出して、そのまま文字数(`.length`)を測ろうものなら……TypeScriptのコンパイラは「ちょっと待って!中に`null`が入っていたらエラーになりますよ!」と優しく、しかし厳しく止めてくれます。

2. ゴミをきれいに分別する救世主:`NonNullable`

ここで登場するのが、今回の主役である `NonNullable` です。

イメージしてみてください。あなたは今、おもちゃ箱の中に混ざってしまった「プラスチックのオモチャ(有効なデータ)」と、「ただのホコリやゴミ(`null` や `undefined`)」を仕分けています。

`NonNullable` は、その名の通り、「おもちゃ箱の中から、`null` や `undefined` という名のゴミを綺麗さっぱり排除して、本当に必要なデータだけを残してくれるお掃除ロボット」のようなものです。

百聞は一見に如かず。実際にコードを見てみましょう。

// 色々なものが混ざった型(ユニオン型)を用意します
type MaybeString = string | null | undefined;

// NonNullableを使って、nullとundefinedを排除した新しい型を作ります
type CleanString = NonNullable;

// 結果、CleanString は実質的に以下のようになります:
// type CleanString = string;

たったこれだけです!
`MaybeString` という「何が入っているか分からない箱」から、`NonNullable` を通すことで、`string` という純粋な型だけを取り出すことができました。

これで、もう「中身が `null` だったらどうしよう……」とビクビクしながらコードを書く必要がなくなります。

—

3. 実務でどう使うの?具体的なシーンを覗いてみよう

「理屈は分かったけれど、実際のWeb制作やアプリ開発の現場でどう使うの?」という疑問が湧いてきますよね。よくある実践的な例をいくつか見てみましょう。

シーン1:APIから送られてくるユーザーデータの整理

Webサイトを作るとき、サーバーからユーザーのプロフィール情報を取得することがよくあります。年齢(`age`)のデータは、登録されていないと `null` が返ってくることがあります。

// サーバーから返ってくるかもしれないユーザー情報の型
interface UserProfile {
id: number;
name: string;
age: number | null | undefined; // 年齢は未登録の可能性がある
}

// ここで、ageの型だけをキレイに取り出したい!
type ValidAge = NonNullable;
// 出来上がる型:number

もし、アプリの別の場所で「年齢が絶対に登録されていることが前提の処理」を書く場合、この `ValidAge`(つまり `number`)を使うことで、余計な `if (age !== null)` のチェックを省略して、スッキリとしたコードを書くことができます。

シーン2:フォームの入力値のバリデーション後

ユーザーが入力フォームに打ち込んだ値を受け取る際、最初は「未入力(`undefined`)」や「未選択(`null`)」の可能性があります。しかし、入力チェック(バリデーション)を無事に通過したあとのデータは、もう `null` や `undefined` であるはずがありません。

// 入力フォームの現在の値(最初は空っぽかもしれない)
let commentInput: string | null = null;

// バリデーションを通過したと仮定して、確実に値が存在する状態にする
function handleValidComment(comment: NonNullable) {
// この中では、commentは100% string型として扱えます!
console.log(`送信されたコメント: ${comment.toUpperCase()}`);
}

// 試しに値をセットして関数を呼んでみる
commentInput = “TypeScriptの勉強中!”;

if (commentInput !== null) {
// TypeScriptに「この瞬間、nullじゃないよ」と教えてあげる
handleValidComment(commentInput);
}

このように、型を厳格に絞り込むことで、予期せぬバグの温床をあらかじめ断つことができるのです。これが、TypeScriptを導入する最大の醍醐味でもあります。

—

4. チーフアーキテクトからのメッセージ

初学者のうちは、TypeScriptの型エラーに出会うたびに「また怒られた……」と心が折れそうになることもあるでしょう。私も昔はそうでした。画面の向こうのコンパイラが、まるで鬼の形相で自分を監視しているように感じたものです。

でも、見方を変えてみてください。TypeScriptの型エラーや、今回ご紹介した `NonNullable` のようなユーティリティ型は、「あなたのコードを一緒に守ってくれる、世界で一番優しい相棒」なんです。

本番環境でユーザーがボタンを押した瞬間にアプリがクラッシュするのを、あなたの代わりに未然に防いでくれているのですから。

最初は難しく感じる型操作も、ひとつずつ引き出しを増やしていけば、パズルを解くように楽しくなってきます。今日知った `NonNullable` も、あなたの強力な武器の一つになりましたね。

焦らず、自分のペースで一歩ずつ進んでいきましょう。あなたのTypeScriptライフが、より快適で楽しいものになるよう、私はいつも応援しています!

コメント

タイトルとURLをコピーしました