带有 Typescript 和样式化组件的 RN FlatList

Posted

技术标签:

【中文标题】带有 Typescript 和样式化组件的 RN FlatList【英文标题】:RN FlatList with Typescript and Styled Components 【发布时间】:2021-02-04 03:56:29 【问题描述】:

SO 社区,

我无法为使用 Typescript 中的样式组件设置样式的 RN FlatList 找出正确的类型定义

所以我有这样的类型IProduct

interface IProduct 
  id: string;
  name: string;

然后我像这样定义FlatList 的类型

<FlatList
  data=products
  renderItem=( item :  item: IProduct ) => (
    <SomeComponent item=item />
  )
  keyExtractor=(item: IProduct) => item.id
/>

一切正常。 Typescript 不会抱怨,但只要我想像这样设置FlatList 的样式

const StyledFlatList = styled.FlatList`
  background-color: 'white';
`;

<StyledFlatList
  data=products
  renderItem=( item :  item: IProduct ) => (
    <SomeComponent item=item />
  )
  keyExtractor=(item: IProduct) => item.id
/>

我收到很多 Typescript 错误

No overload matches this call.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<typeof FlatList, DefaultTheme, , never>): ReactElement<StyledComponentPropsWithAs<typeof FlatList, DefaultTheme, , never>, string | ... 1 more ... | (new (props: any) => Component<...>)>', gave the following error.
    Type '( item :  item: IProduct; ) => JSX.Element' is not assignable to type 'ListRenderItem<unknown>'.
  Overload 2 of 2, '(props: StyledComponentPropsWithAs<typeof FlatList, DefaultTheme, , never>): 
ReactElement<StyledComponentPropsWithAs<typeof FlatList, DefaultTheme, , never>, string | ... 1 more ... | (new (props: any) => Component<...>)>', gave the following error.
    Type '(item: IProduct) => string' is not assignable to type '(item: unknown, index: number) => string'.ts(2769)

index.d.ts(4218, 5): The expected type comes from property 'keyExtractor' which is declared here on type 'IntrinsicAttributes & Pick<Pick<FlatListProps<unknown> & RefAttributes<FlatList<unknown>>, "ref" | "data" | "style" | "ItemSeparatorComponent" | ... 141 more ... | "key"> & Partial<...>, "ref" | ... 144 more ... | "key"> &  ...;  &  ...;  &  ...; '

index.d.ts(4218, 5): The expected type comes from property 'keyExtractor' which is declared here on type 'IntrinsicAttributes & Pick<Pick<FlatListProps<unknown> & RefAttributes<FlatList<unknown>>, "ref" | "data" | "style" | "ItemSeparatorComponent" | ... 141 more ... | "key"> & Partial<...>, "ref" | ... 144 more ... | "key"> &  ...;  &  ...;  &  ...; '

谁能告诉我如何解决这个错误?

【问题讨论】:

【参考方案1】:

经过几次反复试验,我想我找到了一个可行但并不理想的解决方案。

<StyledFlatList<any>
  data=products
  renderItem=( item :  item: IProduct ) => (
    <ProductCard product=item onProductPress=handleOnProductPress />
  )
  keyExtractor=(item: IProduct) => item.id
/>

如果你觉得还可以,请告诉我。

更新 1:

如果我添加建议的代码 sn-p Ben Clayton,prettier 会像这样格式化代码

const StyledFlatList = (styled.FlatList`
  background-color: $colors.silver;
` as unknown) as FlatList;

我得到一个 TS 错误

JSX element type 'StyledFlatList' does not have any construct or call signatures.

更新 2:

我尝试了&lt;React.ElementType&gt; 而不是&lt;any&gt;,而是建议here,这似乎也有效。

<StyledFlatList<React.ElementType>
  data=products
  renderItem=( item :  item: IProduct ) => (
    <ProductCard product=item onProductPress=handleOnProductPress />
  )
  keyExtractor=(item: IProduct) => item.id
/>

【讨论】:

我手边没有 IDE,但 TypeScript 应该已经“知道”项目的类型,因此您应该能够省略 renderItem 和 keyExtractor 参数中的所有类型信息。例如renderItem= ( item ) =&gt; (keyExtractor=item =&gt; . 是的,我也是这么想的。不幸的是,事实并非如此。正如我之前提到的,如果我使用 RN FlatList TS 不会抱怨并推断类型,但是当我使用 styled-components 时它会抱怨,尽管我安装了 @types/styled-components 啊——是的,我明白了。我记得几年前的这个,我们遇到了同样的事情。如果您定义const StyledFlatList = styled.FlatList' background-color: 'white'; ' as unknown as FlatList 会怎样。例如。让 TS 认为 StyledFlatList 只是一个“普通”的 FlatList? 顺便说一句,你能详细说明一下语法吗? const StyledFlatList = styled(FlatList)' background-color: $colors.silver; ' as unknown as FlatList 不起作用 当然很抱歉,我无法在评论中添加正确的语法...尝试将 as unknown as FlatList 放在 StyledFlatList 的声明之后。这迫使 TS 认为 StyledFlatList 是 Fl​​atList 类型。【参考方案2】:

似乎将typeof 添加到另一个建议的解决方案中以更直接的方式解决了这个问题,甚至允许您从道具中排除类型:

const StyledFlatList = (styled.FlatList`
  background-color: 'white';
` as unknown) as typeof FlatList;

<StyledFlatList
  data=products
  renderItem=( item ) => (
    <SomeComponent item=item />
  )
  keyExtractor=(item) => item.id
/>

【讨论】:

【参考方案3】:

这个简单的解决方案对我有用:

interface IProduct 
  id: string;
  name: string;


const StyledFlatList = styled(FlatList as new () => FlatList<IProduct>)`
  background-color: #f7f7f7;
`

【讨论】:

以上是关于带有 Typescript 和样式化组件的 RN FlatList的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 typescript 的样式化组件“as”prop

带有 TypeScript 的样式化组件 .attrs

包括对带有 typescript 的样式化组件主题的媒体查询

使用带有Typescript的样式化组件,prop不存在?

如何在使用 TypeScript 的 create-react-app 中使用带有 babel 插件的样式化组件?

React 和 Typescript,样式化的组件和子组件