結論からいうと
- Truthy/Falsyは絶対利用しない(必ず
if (変数 === undefined)
のように書く) -
if (変数 === undefined || 変数 === null)
といちいち書くのはやばいので、null
は利用しない - 外部APIとの接続で
null
が必要な場合は、必ずラッパーに閉じ込める。ラッパーの外にnull
を持ち出さない。 - Lintで設定しよう
Truthy/Falsyを使いたくない
こうやって書きたい時、よくありますね。
const user = getUser();
if (user){
// userが存在する場合の処理
}
ぼくも上のように書いてたんですが、JavaScript/TypeScriptのTruthy/Falsyの仕様上バグりやすすぎるのでやめることにしました。
JavaScript(TypeScriptも)のTruth/Falsyが罠
上のケース、userがobject
なら(普通ならそうのはず)問題ないけど、string
かnumber
だったらまずい。
TypeScriptでuser: User
と書いたところでそれは保証できない。type User = string
かもしれないし。
それに、「string
かnumber
以外ならTruthy/Falsyを利用してもよい」という運用は複雑でよくなさそう。
Truth/Falsyは、常に利用しない
if (user)
-> if (user !== undefined)
if (!user)
-> if (user === undefined)
と書き換えるのが結局ベストプラクティスとおもう。
nullだったらどうする?
null
とundefined
が混在してるコードでは、こう書かなきゃいけない。
if (user)
-> if (user !== undefined && user !== null)
if (!user)
-> if (user === undefined || user === null)
これは
- 見た目きたねえ
- 書くのだるい
- いつかミスる
ので絶対やめたほうがよさそう。
if (user)
-> if (user != undefined)
if (!user)
-> if (user == undefined)
とすればnull
もみてくれるが、==
は一律で禁止したいので却下。(仮にここだけ==
を利用する運用にした場合、ミスって===
と書くかもだし、そもそも誰かが(未来の自分含め)「あ、ここ==
使ってんじゃん。だめだめ、===
に修正、っと」としうる。ミスに見えうる書き方はだめってダグラス・クロックフォードもいってた。)
null
、やめよう。
そもそもnull
を使うメリットってあるのか?
-
undefined
だと「まだ定義してない」と「明示的にない」の区別がつかないじゃないか!- -> それを区別してどうしたいのか?仮にしたいなら、そんな曖昧な方法じゃなくてもっと明確に用意すべきじゃないか?
このへんの議論はまあいろいろあるので、興味あればこちらなど。
https://media-massage.net/blog/javascript-typescript%E3%81%A7null%E3%82%92%E4%BD%BF%E3%81%86%E3%81%B9%E3%81%8D%E3%81%AA%E3%81%AE%E3%81%8B/
null使わない派
https://typescript-jp.gitbook.io/deep-dive/recap/null-undefined
ということで、undefined
統一した。もし問題がでたらまた考える。
ESLintで設定する
こういうのはLintで機械的にみてほしい。
ESLint - no-null <- 言及してるイシュー
ESLint - strict-boolean-expressions
TSlintなら
[TSLint - strict-boolean-expressions](https://stackoverflow.com/questions/56455915/is-there-eslint-or-tslint-rule-that-checks-that-truthy-falsy-logical-operator-is
https://palantir.github.io/tslint/rules/strict-boolean-expressions/)
no-nullは探してない
課題感
とはいえ毎回if (arg !== undefined)
はごちゃつくから簡単にかけるリテラルがほしいなあ。
あと、外部APIのためのラッパーではどうしてもnull
を使う必要があるけど、(試してないけど)no-nullでそこはいいかんじに除外できるんかな?