type predicateで配列のundefinedを取り除いた型を付ける
型が(T | undefined)[]
になってる配列からundefinedを取り除いたT[]
の配列を作成しようとした時のこと
JS的には問題なかったけどTSで型の推論が(T | undefined)[]
のままになっていてどうしたらいいんだとなった時に解決できた時のメモ
先に結論を書くと、解決策はほぼ下記のQiita記事の通りである
めっちゃ参考になりました、ありがとうございます!
ほぼ繰り返しになるのだが、type predicateを今までクールに使えたことがなくてちょっと感動したのでメモとして残しておく
背景
本題に入る前にちょっと背景から
ある配列に対してmapを使って新しく配列を取得したかったんだけど、ある条件の時はその要素はスキップしたかった
イメージとしては以下のような感じ
なんだけど、mapの中でcontinueとかbreakとかって使えたっけ?って思ったら案の定使えなかった
大人しくfor...of
使うかーと思って調べたら配列そのものはイテレーターオブジェクトじゃない?。。
ので、entries()
を使って下記のようにすると一応行けた
行けたんだけどなんかクールじゃない←
好みの問題かもだけど、そもそもfor...of
で配列に対してpushしてくみたいな操作あんま好きじゃなくて、mapとか使った方が関数型っぽくて好き
ってことで、できはしたんだけどmap使ってなんとかしたいなと思った
mapの中でreturnするとundefinedが返るから配列の中にundefinedが混じる可能性がある
当然型もundefinedのユニオン型の配列になる
てなわけでundefined混ざった後にundefinedだけ取り除けばいいじゃんと思い、そうすることにした
本題
まずは最初やろうとした処理の型がどうなるかを見る
undefinedのユニオン型になってしまって困った
ので、undefinedが混ざった配列をフィルタリングする処理を書いてみた
これでめでたし、と思ったら型推論が(File | undefined)[]
のままだった…!
もちろんJSの処理的にはundefinedが取り除かれたものになっている
が、TSはそこまで推論できないらしい
調べたらtype predicate(ユーザー定義タイプガード)を使えばいい感じに推論できるようになるとのこと
下記のようにすればundefinedが取り除かれた型で推論してくれるようになった!
返ってくる型がundefinedを除いたものであると教えてあげることで希望通りの型になった
ちなみにこのタイプガード嘘をつこうと思えばつけてしまうので使用には注意が必要
ちゃんと推論してくれるようになるライブラリとか誰か作ってそうな気はするけど調べてない
ちなみにflatMap使って書くこともできるらしい
flatMapでこんな使い方できるの初めて知った
けど、直感的にfilterの方が読みやすい気がする
あとやっぱtype predicate使いたい笑
安全性考えたらflatMapの方がいいのかもしれないけど
追記
type predicate使えてテンション上がってたけど、後々よくよく考えたらそもそも最初からfilter使ってからmapしたらtype predicate使うまでもなく処理できてこれでよかったんじゃないかと思った
うん、型安全性が保証されるしこっちの方がいいな
mapの中でskipしたい条件がある場合は最初にfilterかけるべきだなと学んだ
一応この記事はtype predicateの使い方のために残しておく
まとめ
TSおもしれー!!!