react-native-masonry-list icon indicating copy to clipboard operation
react-native-masonry-list copied to clipboard

TypeScript: Type 'unknown' is not assignable to type 'IntrinsicAttributes'

Open sofi-algoritcom opened this issue 1 year ago • 1 comments

Describe the bug When using the MasonryList component in a TypaScript project, the renderItem prop param item 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 or ScrollView instead, I don't get this warning.

To Reproduce Steps to reproduce the behavior:

  1. Create TypeScript project.
  2. Define this constants:
interface PostPreviewProps {
  id: string;
  imgUrl: string;
}

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',
  },
];
  1. Define the following component to render the item:
function PostPreview(props: PostPreviewProps): JSX.Element {
  return (
    <View>
      <Image
        source={{ uri: props.imgUrl }}
      />
    </View>
  );
}
  1. Render the following:
<MasonryList
  data={posts}
  renderItem={({ item }) => (
    <PostPreview {...item} />
  )}
/>
  1. See ts problem

Expected behavior The item param from the renderItem callback should have type PostPreviewProps, since the data value (posts) is an array of such item type. Both FlatList and ScrollView do this automatically, but this MasonryList component says item is type unknown, which causes the ts problem reported when passed item as props to the PostPreview component.

Screenshots Captura de pantalla 2024-04-03 a las 16 03 52 Captura de pantalla 2024-04-03 a las 16 08 09

sofi-algoritcom avatar Apr 03 '24 14:04 sofi-algoritcom

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>

Fexxix avatar Aug 04 '24 19:08 Fexxix