Open sofi-algoritcom opened 6 months ago
This might just be a problem with react's types itself. Let me explain:
// the signature for the MasonryList is this
declare const MasonryList = <T>(props: Props<T>) => ReactElement;
// this should work fine but this isn't the type which the library consumer ends up using
// because the component is memoized so the .d.ts file instead exports this
declare const _default: React.MemoExoticComponent<typeof MasonryList>;
// this, for some reason, breaks sound typing in generic components
Paste this code into your IDE to see what i mean
import React, { memo } from "react"
import { FlatList } from "react-native"
type ListProps<T> = {
data: T[];
};
const List = <T,>({ data }: ListProps<T>) => {
return (
<FlatList
data={data}
renderItem={() => null}
keyExtractor={() => ""}
/>
);
};
<List
// hover over data to see that it is correctly typed
data={[1,2]}
/>
const MemoList = memo(List)
;() => <MemoList
// hover over data to see that it is not correctly typed and is instead typed as unknown[]
data={[1, 3]}
/>
// also the type of this below and the `MemoList` are not the same
type MemoListType = React.MemoExoticComponent<typeof List>
Describe the bug When using the MasonryList component in a TypaScript project, the
renderItem
prop paramitem
is not being typed as the elements given to the data prop array, but it is type 'unknown' so when rendering the item, ts raises this problem.If I use
FlatList
orScrollView
instead, I don't get this warning.To Reproduce Steps to reproduce the behavior:
const posts: PostPreviewProps[] = [ { id: '1', imgUrl: 'https://img.freepik.com/free-photo/delicious-donuts_144627-6267.jpg?t=st=1708687137~exp=1708690737~hmac=f9cf5f46c098a440e9581533fe07c587d300dfc22b44d0cc7cdb1b6810503314&w=1480', }, { id: '2', imgUrl: 'https://img.freepik.com/free-photo/vertical-shot-fox-walking-rocks-forest_181624-31966.jpg?t=st=1708686685~exp=1708690285~hmac=b7d67c6f8bf2576069aaa00308da904b12ae956275498340427b94165f880a60&w=996', }, ];
function PostPreview(props: PostPreviewProps): JSX.Element { return (
); }
<MasonryList data={posts} renderItem={({ item }) => ( <PostPreview {...item} /> )} />