TypeScript is really great, just for the moment I feel like I work for TypeScript more than TypeScript works for me.
I have a FlatList that renders restaurant results in a Carousel.
const renderRestaurantRows = ({ item }) => (
<Carousel
id={item.id}
name={item.name}
/>
);
const renderBottomSheetRestaurantList = () => (
<View style={[styles.listView, { height: topSnapPoint }]}>
<FlatList
data={restaurants}
keyExtractor={(item) => `row-${item.id}`}
renderItem={renderRestaurantRows}
/>
</View>
);
TypeScript complains about item with Binding element 'item' implicitly has an 'any' type - makes sense. So I try to tell it what to expect:
interface RestaurantItem {
item: {
id: string;
name: string;
};
}
const renderRestaurantRows = ({ item }: RestaurantItem) => (
<Carousel
id={item.id}
name={item.name}
/>
);
But then TS complains about data={restaurants] with Type 'Restaurant[]' is not assignable to type 'readonly { id: string; name: string; imageUrl: string; rating: number; reviews: number; } and a ton of other information.
Any chance someone can share a solution AND explain how to find such a solution in the future for other similar cases?
UPDATE
restaurants is fetched from a custom hook. It is defined as an array of Restaurant objects:
interface Restaurant {
id: string;
name: string;
}
export default function useRestaurantSearch() {
const [restaurants, setRestaurants] = useState<Restaurant[] | null>(null);
...
UPDATE 2
Guys thanks for the comments, following the two suggestions, I rewrote the code:
import useRestaurantSearch from '../hooks/useRestaurantSearch';
export default function RestaurantPage() {
const renderRestaurantRows = ({ item }: Restaurant) => (
<Carousel
id={item.id}
name={item.name}
/>
);
const renderBottomSheetRestaurantList = () => (
<View style={[styles.listView, { height: topSnapPoint }]}>
<FlatList
data={restaurants}
keyExtractor={(item) => `row-${item.id}`}
renderItem={renderRestaurantRows}
/>
</View>
);
This time I am getting an error for { item }: Restaurant with Cannot find name 'Restaurant'. And it's not surprising because Restaurant is defined in an external hooks file ../hooks/useRestaurantSearch. Do I need to import it somehow?
UPDATE 3
After hours of playing around with this, I got to this point:
const renderRestaurantRows = (result: { item: Restaurant }) => {
return <Carousel {...result.item} />;
};
const renderBottomSheetRestaurantList = () => (
<View style={[styles.listView, { height: topSnapPoint }]}>
<FlatList
data={restaurants}
keyExtractor={(item) => `row-${item.id}`}
renderItem={renderRestaurantRows}
/>
</View>
);
renderItem generates an object which contains each restaurant data under an item key. So for example, one of the objects could be:
{
"index": 18,
"item": Object {
"coordinates": Object {
"latitude": 123,
"longitude": -123,
},
"id": "dfg987fshjsdfh",
"name": "Yummy Food",
},
"separators": Object {
"highlight": [Function highlight],
"unhighlight": [Function unhighlight],
"updateProps": [Function updateProps],
},
}
When I pass a result object, I can let TS know about item inside the object and casting it to the Restaurant type. I do it with (result: { item: Restaurant }). However, when I try to directly destructure the resultobject with({ item }: Restaurant)it gives me the errorProperty 'item' does not exist on type 'Restaurant'`. Any idea why?
