J. *_*ers 1 object typescript react-native typescript-typings react-native-flatlist
我正在用TypeScript构建一个React Native应用程序。renderItem抱怨解构后的项目隐式具有any类型。我用Google搜索,发现了这个问题,并试图实现他们在这里任教,在类型组合index.d.ts中的@types包本机作出反应。
export interface Props {
emotions: Emotion[];
}
class EmotionsPicker extends PureComponent<Props> {
keyExtractor = (item, index) => index;
renderItem = ({ item }) => (
<ListItem title={item.name} checkmark={item.checked} />
);
render() {
return (
<FlatList<Emotion>
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
data={this.props.emotions}
/>
);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用。我该如何指定商品类型Emotion?
小智 39
我知道这是一个老问题,但谷歌搜索它的人可能仍然会欣赏它。
import { FlatList, ListRenderItem } from 'react-native'
/*
.
.
.
*/
renderItem: ListRenderItem<Emoticon> = ({ item }) => (
<ListItem title={item.name} checkmark={item.checked} />
);
Run Code Online (Sandbox Code Playgroud)
小智 19
我找到了一个对我来说非常有效的解决方案:
import { FlatList, ListRenderItemInfo } from 'react-native';
<FlatList
data={data}
renderItem={({ item }: ListRenderItemInfo<ItemType>) => (
<ItemComponent item={item} />
)}
keyExtractor={(item: ItemType) => item.id}
/>
Run Code Online (Sandbox Code Playgroud)
J. *_*ers 11
我找到了一个解决方案(尽管我不知道它是否理想):
renderItem = ({ item }: { item: Emotion }) => (
<ListItem title={item.name} checkmark={item.chosen} />
);
Run Code Online (Sandbox Code Playgroud)
小智 7
如果不是内联函数,解构时从 React 导出的正确类型是ListRenderItemInfo<ItemT>:
export interface ListRenderItemInfo<ItemT> {
item: ItemT;
index: number;
separators: {
highlight: () => void;
unhighlight: () => void;
updateProps: (select: "leading" | "trailing", newProps: any) => void;
};
}
Run Code Online (Sandbox Code Playgroud)
这是因为在renderItem定义时间时,TypeScript无法知道它应该作为的renderItem支持FlatList。
如果您已跳过变量并直接将属性放入prop中,则TypeScript应该能够正确推断出它:
export interface Props {
emotions: Emotion[];
}
class EmotionsPicker extends PureComponent<Props> {
render() {
return (
<FlatList<Emotion>
keyExtractor={(item, index) => index}
renderItem={({ item }) => <ListItem title={item.name} checkmark={item.checked} />}
data={this.props.emotions}
/>
);
}
}
Run Code Online (Sandbox Code Playgroud)
我觉得这里的答案只解决了如何在更好的情况下修复,在更坏的情况下绕过类型检查,但无法解释为什么它不起作用或者为什么应该按原样输入。
我想更清楚地解释为什么这对大多数人来说会失败,因为即使在官方的React-Native Wiki 上,它的记录也非常少。
组件FlatList方法不需要通常用于传递(即)标准 React 元素构造函数的渲染函数(props) => JSX.Element。
无论好坏,FlatList的renderItem方法的键入方式如下:
type ListRenderItem<ItemT> = (info: ListRenderItemInfo<ItemT>) =>
React.ReactElement | null;
Run Code Online (Sandbox Code Playgroud)
这是因为它不需要直接元素构造函数,就像您renderItem在大多数 React 模式中习惯的那样标准构造方法。
相反,它需要一个特定类型的回调。这是为了优化目的的内部处理,但在输入时仍然相当笨重。
export interface ListRenderItemInfo<ItemT> {
item: ItemT;
index: number;
separators: {
highlight: () => void;
unhighlight: () => void;
updateProps: (select: 'leading' | 'trailing', newProps: any) => void;
};
}
Run Code Online (Sandbox Code Playgroud)
因此,这意味着我们应该将我们自己的内部renderItem视为回调,以及传递特定<ItemT>泛型的特定项目道具
type Props = {
emotions: Emotion[]
}
// This is the standard React function component
const Item = (({ title, checked }): Emotion) => (
<ListItem title={title} checked={checked} />
)
// This is the callback for constructing the function component
const renderItem: ListRenderItem<Emotion> = ({ item }: ListRenderItemInfo<Emotion>) => (
<Item title={item.title} checked={item.checked} />
)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,乍一看这可能相当令人困惑并且很容易混淆。在ListRenderItem<T>Tell 打字稿中,我们希望创建一个类型T(通用参数)的函数,然后构造(返回)一个Reat.ReactElement | null. 但由于 React 组件本身就是函数,我们仍然需要传递函数来创建一个。这就是混乱和类型错误的根源。
这本质上是
ListRenderItem<T>ListRenderItemInfo<T>prop的特定 propTypeitem(props: T) => JSX.Element而不是传递道具并从中创建元素的标准方式。这也是您收到以下打字稿错误的原因:
Property 'property name' does not exist on ListRenderItem<any>
Run Code Online (Sandbox Code Playgroud)