例えば、
type HOGE = PIYO | undefined;
と言うような型があったとして、Typescriptの場合ifやcase文でPIYO型として処理を行うことが出来る。
//hogeはHoge型の変数とする
if(hoge){
//この中ではhogeはpiyo型として扱える
}
一方で、Array.filterではそのような絞り込みは行われない
//hogeArrayはHoge型の配列とする
hogeArray.filter(hoge => !!hoge); //これの戻り値はPIYO[] ではなく HOGE []
ちょっと使い勝手が悪い。
対応策
ユーザー定義TypeGuardを使う
変数名 is 型名 を戻り値に書く関数で任意の方法でTypeGuardをかけられるが、
これを使うパターンだとfilterでもTypeGuardがかかる
const isPIYO = (hoge:HOGE): hoge is PIYO => {
return !!hoge;
}
ただし、この方法だとコンパイルは通るものの、
実質キャストをかけているだけなので、isPIYOの中身が正しいかどうか静的チェックがかかるわけではない。
isPIYOの実装を間違えていると実行時に型で防げたはずのエラーが出る可能性がある。
flatMapを使う
他にも似たような方法はいくつかあるものの、結局どこかしらでキャストをかけることになる。
そこで、静的型チェックがかかったままfilterと同じことが出来ないか色々試した結果、flatMapで何とかなるということを発見した。
hogeArray.flatMap(hoge => !!hoge ? [hoge]:[]);//戻り値はPIYO配列
ただ、filter後につなげる処理がmapだった場合はまだしも、
純粋にfilter用途でこれをやると気持ち悪いかも知れない。
また、Array.flatMapはES2019の機能なので生TypeScriptでは使えない。
Babel辺りと組み合わせて使う必要がある。