2019/11/11追記
TypeScript3.7からOptional Chainingが導入されました!
ここで記述されている?.
演算子が使えるようになったため、以下の議論が比較的きれいにかけるようになりました。
TypeScript3.6までのNullable
たとえば、こんなコードがある。
document.getElementById('loader').style.display = 'none'
TypeScriptではJavaScriptで↑のように書けていたコードはそのまま書くと、
error TS2531: Object is possibly 'null'.
と怒られるため、↓のように書かなくてはならない。
const loader = document.getElementById('loader')
if (loader) {
loader.style.display = 'none'
}
これはdocument.getElementById()
の返す型がHTMLElement | null
であるため、
Nullチェック
を行えという至極真っ当な主張である。
言ってしまえば、JavaScriptの方のコードは潜在的なバグあるということに気付かされる場面でもある。
しかし、みなさんにはどうでもいいかもしれないがこういったことでif文を書き、ネストが一つ深まるのが個人的には好きではない。
ではどうするか?
他の言語ではどうなの?
他の言語の場合、**Null条件演算子(Safe Navigation Operator)
**というものがある。
Null条件演算子
を使用した場合、nullが検出されて以降のメソッドやフィールドの評価を行わずにnullをその結果として返す。
たとえば、C#やSwiftだったら以下のように書けるはずだ。
document.getElementById("loader")?.style.display = "none"
確かに、↑のように書けることができれば、いけ好かないif文を書く必要がなくなる。
しかし、TypeScriptではこのような演算子はまだ存在しないようだ。
似たような文法は確かに存在していて、
document.getElementById('loader')!.style.display = 'none'
と書けることにはたしかに書ける。
調べるとx!演算子
はNon-null Assertion Operator
というものらしい。
x
がNon-null
、Non-undefined
と断定できる場合に使用できる。
しかしこれではJavaScriptのコードと何ら変わりはない。
今回に関して言えば、いけ好かないif文を書いたほうが数億倍マシまである。
というのもNull条件演算子
を見たあとにこれでは悲しすぎる。
ではどうする?
一時期、Null許容型
やNull安全型
に関しての議論がよくされていた。
タイトルのNullable
がNull許容型
に当たる。
document.getElementById()
でいえばHTMLElement | null
をしてNull許容
とここではしておく。
TypeScriptを使用する際に、私がよく使う便利なライブラリにfp-tsというライブラリがある。
これはTypeScriptに関数型プログラミングの考え方を導入するためのライブラリである。
幸いなことに、提供するものの中にはNull安全
でおなじみのOption
がある。
毎度、TypeScriptを使用するときにこのライブラリも使うんだから、これ利用してどうにかきれいに書けないかと考えることにした。
とりあえず書いてみた。
import { pipe } from 'fp-ts/lib/pipeable'
import { fromNullable, map } from 'fp-ts/lib/Option'
pipe(
document.getElementById('loader'),
fromNullable,
map((loader) => { loader.style.display = 'none' })
)
律儀に改行しまくったため、長く見えるが、if文が消えたので良しとする。
やっていることとしてはNullable型
からOption型
へ変換し、document.getElementById('loader')
がnull
ではなかったらmap
に渡した関数が適用されるといった感じになる。
この程度のことでOption
をわざわざ引っ張り出すのは大げさかもしれないが規模が大きくなるに比例して、Null安全
の概念を導入することは有利に働くと思うのでこういったことで慣れておくのもいいだろう。