🤲

FlatListで 'ArrayLike<>' must have a '[Symbol.iterator]()' method

2023/05/05に公開

概要

react native expoのsdkを45から48にアップして色々対応していたら、FlatListのonEndReached

 error TS2488: Type 'ArrayLike<>' must have a '[Symbol.iterator]()' method that returns an iterator.

というtypescriptのエラーが出ました。他のエラーに比べ対応に手こずったのでメモ残します。

原因

コードはこんな感じ

export type PageForSearch = {
  current: number;
  next: number | null;
  count: number;
};

export type JobSeachResponse = {
  jobs: JobForSearch[];
  page: PageForSearch;
};

const [response, setResponse] = React.useState<JobSeachResponse>();
 
<FlatList
  ...
  onEndReached={(data, nextPage) => {
    return fetchJobsForSearch(userId, secureCode, nextPage).then(resp =>
      setResponse({
        jobs: [...data, ...resp.jobs],
        page: resp.page,
      })
    );
  }}
/>

この[...data]とスプレッド演算子で配列をマージしてるところでエラーが出ました。

どのバージョンかはっきりしませんがFlatListに渡すdataの型がReadonlyArray<ItemT>からArrayLike<ItemT>に変わったようです。

https://github.com/facebook/react-native/pull/36236

https://github.com/facebook/react-native/blob/714b502b0c7a5f897432dbad388c02d3b75b4689/packages/react-native/Libraries/Lists/FlatList.d.ts#L46

配列だけでなくより柔軟なソースに対応しようというわけですね。

ArrayLikeにスプレッド演算子は使えないようなのでエラーが出ていたわけです(実際には配列が来てるのでコードは動きますが)。

解決

どうしようか結構悩みましたが、response.jobsは配列であることが明示されてるので

onEndReached={(data, nextPage) => {
 return fetchJobsForSearch(userId, secureCode, nextPage).then(resp =>
   setResponse({
     jobs: [...(data as JobForSearch[]), ...resp.jobs],
     page: resp.page,
   })
 );
}}

にしちゃいまいした。

jobs: [...Array.form(data), ...resp.jobs],

とういのも考えたんですけどぶっちゃけ無駄な処理かなと。

もう少しうまい方法があったら教えてください。

Discussion