as を使わずに配列から undefined を 型安全に取り除く
こんにちは kimizuy です。
今回は as
で型キャストしないで、配列の要素から undefined
を型安全に取り除く方法をご紹介します。
前提
例えば以下のような配列があるとします。
type Person = { name: string; age: number }
// people は (Person | undefined)[] 型
const people = getPeople()
ここから filter(Boolean)
を使って undefined
の値を実質的に取り除いても型にはまだ undefined
が含まれたままです。
const filtered = people.filter(Boolean)
// → (Person | undefined)[]
この配列の中身を取り出して利用する場合、常にオプショナルな値として存在チェックが必要になります。早い段階で中身に加えて型も Person
型のみの配列にしたいですね。
その対策として手軽なのは as
を使って型を上書きする方法です。
const filtered = people.filter(Boolean) as Person[]
実際の値では undefined
が取り除けているため、これで十分だとも思えますが「as を使うことに躊躇いのない人なんだ…」と周囲に思われるのは気が気ではないですね。
また getPeople()
の返す値に変化があった場合は as
部分のメンテナンスもしなければならず、人間の脳内メモリを消費する形で気をつけることが増えてしまいます。
TypeScript の機能を活かしてスマートな方法を模索したいところです。
解決方法
ユーザー定義の型ガードを使います。
ユーザー定義の型ガードとは instanceof
や typeof
のように型を特定する機能をユーザーが柔軟に定義できる機能です。
以下のように is
を使って引数の型を絞り込むことができます。
const existPerson = (person: Person | undefined): person is Person => {
return !!person
}
const people = getPeople()
const filtered = people.filter(existPerson)
// → Person[]
existPerson()
は boolean
を返す関数です。true
だった場合は person is Person
、つまり引数の person
が Person
型であることを保障してくれます。
アロー関数で書けば、さらに短く書くこともできます。
const filtered = people.filter((person): person is Person => !!person)
参考
Filtering undefined elements from an array in TypeScript
(filter(Boolean)
による型推論の機能を追加する動きが昔あったようです)
おわりに
ユーザー定義の型ガードは書くのに面倒なイメージがありましたが、記事としてまとめてみると意外と手軽に書けそうな気がしますね。
以上、お読みいただきありがとうございました。
今すぐの転職でなくてもOKです!まずはお話しませんか?
現在弊社では一緒にお仕事をしてくださるエンジニアさんやデザイナーさんを積極募集しています。まずはカジュアルな面談で、お互いに大事にしていることをお話できたらうれしいです。詳しい応募要項は以下からチェックしてください。
- React, Next.js を得意とするフロントエンドエンジニア募集要項
- シニアクラスのフロントエンドエンジニア募集要項
- 抽象的な物事を具体的な機能にビジュアライズできるUIデザイナー募集要項
- UIデザイナーとして手ざわりのいいUIを作りたい業務委託パートナーさん募集(Wantedly)
パートナー契約へのお問い合わせもお仕事へのお問い合わせも、どちらもいつでも大歓迎です。まずはオンラインでの面談でお話しましょう。ぜひお気軽にお問い合わせください!
話をしてみたい!