as 型アサーションでの失敗、そして配列から nullable な要素を除外する方法

こんにちは、 Gaji-Labo フロントエンドエンジニアの石垣です。

今回は案件でコードを書いていた際に経験した as (型アサーション)での失敗と、配列にある nullable な要素を除外する方法についてまとめたいと思います。

配列から undefined を除外したい

案件でコードを書いていた際に、 undefined になる要素が入りうる配列から undefined を除外したいというケースがありました。

<ExampleComponent items={array} />
// items の型は string[]
// array の型は (string | undefined)[]

JSで単純に undefined を除外するのであれば filter メソッドが使えます。

<ExampleComponent items={array.filter((item) => !!item)} />

しかし、TypeScript を使っていると依然として以下のようなエラーが表示されます。

型 '(string | undefined)[]' を型 'string[]' に割り当てることはできません。
  型 'string | undefined' を型 'string' に割り当てることはできません。
    型 'undefined' を型 'string' に割り当てることはできません。ts(2322)

型情報からも nullable な要素を除去する必要があります。

as で型アサーションをしてみる

一旦、 as で型アサーションをしてみました。

<ExampleComponent items={array.filter((item) => !!item) as string[]} />

そうするとコード上でエラーは発生しなくなりました。

が、 画面上で確認していると、ある特定の場面でエラーが表示されることに気づきます。

配列自体を string[] で型アサーションしていたので、配列自体が undefined のケースも黙殺されてしまっていたのです。

ユーザー定義の Type Guard を使う

解決策を調べていたところ、配列の型から undefined を除外するには除外するには NonNullable というユーティリティ型が使えることを教えてもらいました。

上記の items に NonNullable を適用するには、

<ExampleComponent
  items={array.filter(
    (item): item is NonNullable<typeof item> => !!item
  )}
/>

(args): args is NonNullable<typeof args> と書くことで、ユーザー定義の Type Guard を使うことができます。これは配列ではなく引数の型を定義できるものです。
これでエラーも出ず、配列自体が undefined のケースにも対応することができるようになりました。

まとめ

今回の件で二つのことを学びました。

  • 配列から nullable な要素を除外する方法
  • as 型アサーションは最後の手段として安直に使わない

as の危険性を身を以て知る結果になりました……。
今後、コードを書く上でもレビュー観点でも as の登場はなるべく防いでいきたいと思います。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

投稿者 Ishigaki Shotaro

アシスタントエンジニアとしてHTML/CSS/JavaScriptの実装やRailsの組み込み、スタイルガイドの構築などを担当しています。 業務の中でさまざまな学びを吸収しながら、文書構造やアクセシビリティに目を向けたマークアップの学習やJavaScriptの学習などを行っています。チームに貢献できるエンジニアとなるために日々奮闘中です。