nullとundefinedの違い

JavaScriptには、値の不在に関係するnullundefinedという別々のプリミティブ値がある。

両者は同じ値ではなく、TypeScriptでも別の型として扱われる。

undefined

undefinedは、値がまだ設定または提供されていない場面で現れる。

たとえば、初期値を与えていない変数や、存在しないプロパティを読み取った結果はundefinedになる。

let result
console.log(result) // undefined
 
const user = {}
console.log(user.nickname) // undefined

省略された関数の引数や、値をreturnしなかった関数の戻り値もundefinedになる。

このように、undefinedはJavaScriptの実行結果として自動的に現れることが多い。

null

nullは、値が存在しないことをプログラムやAPIが明示するときに使われることが多い。

type User = { name: string }
 
let selectedUser: User | null = null

この例では、selectedUserに利用者情報が入る可能性はあるが、現在は選択されていないことをnullで表している。

ただし、この使い分けは言語が強制する規則ではない。

プログラムからundefinedを明示的に代入することもできる。

別々の値と型

string | null | undefinedは一つの曖昧な型ではなく、値が次の三種類のいずれかになることを表すユニオン型である。

flowchart TB
    T["string | null | undefined"]
    T --- S["string<br/>文字列がある"]
    T --- N["null<br/>値がないことを明示"]
    T --- U["undefined<br/>値が設定または提供されていない"]

この図の線は処理の順番ではなく、ユニオン型を構成する選択肢の分類を示している。

ECMAScript仕様は、undefinednullをそれぞれ一つの値だけを持つ別々の言語型として定義している。

TypeScriptでの扱い

strictNullChecksが有効な場合、nullundefinedは通常のstringnumberとは別の型として検査される。

const title: string = null
// エラー: nullはstringに代入できない

nullを許可する場合は、ユニオン型で明示する。

let title: string | null = null
 
title = "TypeScript入門"

undefinedも許可する場合は、同じように型へ追加する。

let title: string | undefined = undefined
 
title = "TypeScript入門"

値を使う前には、実際の値が入っているか確認する。

function printTitle(title: string | null) {
  if (title === null) {
    console.log("タイトルなし")
    return
  }
 
  console.log(title.toUpperCase())
}

この検査により、if文の後ではtitlestringであることをTypeScriptが判断できる。

参考資料