JavaScript(と、TypeScript)は、null
とundefined
という2つのボトム型(bottom type)があります。これらは異なる意味を持っています。
初期化されていない: undefined
。
現在利用できない: null
。
現実としては、あなたは両方とも対応する必要があります。==
でチェックしましょう:
/// Imagine you are doing `foo.bar == undefined` where bar can be one of:console.log(undefined == undefined); // trueconsole.log(null == undefined); // true// You don't have to worry about falsy values making through this checkconsole.log(0 == undefined); // falseconsole.log('' == undefined); // falseconsole.log(false == undefined); // false
== null
を使ってundefined
と null
を両方ともチェックすることを推奨します。一般的に2つを区別する必要はありません。
function foo(arg: string | null | undefined) {if (arg != null) {// `!=` がnullとundefinedを除外しているので、引数argは文字列です}}
1つだけ例外があります。次に説明するルートレベル(root level)のundefinedの値です。
== null
を使うべきだと言ったことを思い出してください。もちろん、覚えているでしょう(今、言ったばかりなので)。それは、ルートレベルのものには使用しないでください。 strictモード(strict mode)でfoo
を使うとき、foo
が定義されていないと、ReferenceError
exceptionが発生し、コールスタック全体がアンワインド(unwind)されます。
strictモードを使うべきです...現実としては、TSコンパイラはモジュール(modules)を使うときに、自動的に
"use strict";
を挿入します...後で解説を行うので、詳細は省略します:)
変数がglobalレベルで定義されているかどうかを確認するには、通常、typeof
を使用します:
if (typeof someglobal !== 'undefined') {// someglobal is now safe to useconsole.log(someglobal);}
TypeScriptにおいて、あなたは、変数と構造を分離して型を記述することができます。下記のように書く代わりに:
function foo(){// if Somethingreturn {a:1,b:2};// elsereturn {a:1,b:undefined};}
型アノテーションを使用すべきです。
function foo():{a:number,b?:number}{// if Somethingreturn {a:1,b:2};// elsereturn {a:1};}
Nodeスタイルのコールバック関数(例: (err, somethingElse)=> {/* something */}
)は、エラーがなければ err
にnull
を設定して呼び出されます。開発者は一般的にtruthyチェックを行います:
fs.readFile('someFile', 'utf8', (err,data) => {if (err) {// do something} else {// no error}});
独自のAPIを作成するときは、一貫性のためにnull
を使用することは、良くはありませんが、問題ありません。とはいえ、できればPromiseを返すようにするべきです。そうすれば、err
がnull
かどうかを気にかける必要はなくなります(.then
と.catch
を使います)。
ひどい関数の例:
function toInt(str:string) {return str ? parseInt(str) : undefined;}
このほうがはるかに良い:
function toInt(str: string): { valid: boolean, int?: number } {const int = parseInt(str);if (isNaN(int)) {return { valid: false };}else {return { valid: true, int };}}
JSON標準では、null
のエンコードはサポートしていますが、undefined
のエンコードはサポートしていません。値がnull
である属性を持つオブジェクトをJSONにエンコードするとき、その属性はnull
値とともにJSONに含まれますが、値がundefined
である属性は完全に除外されます。
JSON.stringify({willStay: null, willBeGone: undefined}); // {"willStay":null}
結果として、JSONベースのデータベースは、null
はサポートしますがundefined
はサポートしないことがあります。null
値を持つ属性はエンコードされるため、オブジェクトをエンコードしてリモートのデータストアに送る前に、ある属性値をnull
にすることで、その属性を削除したいという意図を伝えることができます。
属性値をundefined
にすると、その属性名はエンコードされないため、データの保存と転送のコストを節約することができます。しかし、これによって値を削除することと値が存在しないことの意味づけが複雑になってしまいます。
TypeScriptチームは、null
を使いません: TypeScriptコーディングガイドライン。 そして、問題は起きていません。 Douglas Crockfordはnullはbad ideaであり、誰もがundefined
だけを使うべきだと考えています。
しかし、Nodeスタイルのコードでは、Error引数にnull
が標準で使われています。これは現在利用できません
という意味です。私は個人的に、ほとんどのプロジェクトにおいて、意見がバラバラのライブラリを使っていますが、== null
で除外するだけなので、2つを区別しません。