键入 React 组件工厂函数
Posted
技术标签:
【中文标题】键入 React 组件工厂函数【英文标题】:Typing a React Component Factory Function 【发布时间】:2021-09-24 14:28:03 【问题描述】:给定类型
type EnumerableComponentFactory = <C, I>(config:
Container: React.ComponentType<C>;
Item: React.ComponentType<I>;
) => React.FC< items: I[] >;
使用以下实现
const Enumerable: EnumerableComponentFactory =
( Container, Item ) =>
( items ) =>
(
<Container>
items.map((props, index) => (
<Item key=index ...props />
))
</Container>
);
和预期用途
const UnorderedList = Enumerable(
Container: ( children ) => <ul>children</ul>,
Item: ( title : title: string ) => <li>title</li>,
);
<UnorderedList items=[title: "Something"] />
我观察到以下 TypeScript 错误
Type ' children: Element[]; ' is not assignable to type 'C'.
'C' could be instantiated with an arbitrary type which could be unrelated to ' children: Element[]; '.ts(2322)
这引出了我的问题:我需要设置哪些类型约束来解决此错误?
我尝试将类型更改如下:
type EnumerableComponentFactory = <C extends children?: Element[] , I>(config:
Container: ComponentType<C>;
Item: ComponentType<I>;
) => (props: items: I[] ) => ReturnType<FC<I>>;
但这会产生一个更加神秘的错误消息,为了简洁起见,我将省略它。
附:该函数本身实际上完全符合预期。只是编译器出错了。
【问题讨论】:
【参考方案1】:我能够更改您的代码以使其正常工作,同时还接受其他要传递给容器的道具:
type EnumerableComponentFactory = <C, I>(config:
Container: React.ComponentType<C & children: React.ReactNode[] >;
Item: React.ComponentType<I>;
) => React.ComponentType<C & items: I[] >;
const Enumerable: EnumerableComponentFactory = ( Container, Item ) => (
props
) => (
<Container ...props>
props.items.map((props, index) => (
<Item key=index ...props />
))
</Container>
);
这允许例如这个:
const ContainerWithBorder: React.ComponentType< color: string > = (props) => (
<div style= border: `2px solid $props.color` >
<ul>props.children</ul>
</div>
);
const ComplexList = Enumerable(
Container: ContainerWithBorder,
Item: ( title : title: string ) => <li>title</li>
);
<ComplexList items=[ title: "Something" ] color="red" />
ComplexList
组件带有 color
属性的打字/智能感知。
可以在here 找到带有原始示例和ComplexList
示例的游乐场。
【讨论】:
【参考方案2】:是否需要保留C
泛型参数?
import React, FC, ComponentType, PropsWithChildren from "react";
type EnumerableComponentFactory = <I>(config:
// or Container: FC< children: JSX.Element[] >;
Container: FC<PropsWithChildren<object>>;
Item: ComponentType<I>;
) => FC< items: I[] >;
const Enumerable: EnumerableComponentFactory =
( Container, Item ) =>
( items ) =>
(
<Container>
items.map((props, index) => (
<Item key=index ...props />
))
</Container>
);
const UnorderedList = Enumerable(
Container: ( children ) => <ul>children</ul>,
Item: ( title : title: string ) => <li>title</li>,
);
const result = <UnorderedList items=[ title: "Something" ] />;
【讨论】:
以上是关于键入 React 组件工厂函数的主要内容,如果未能解决你的问题,请参考以下文章
强烈键入 react-redux 与 typescript 连接
使用 react-router-dom 在组件基础上键入 location.state 属性
如何在带有 TypeScript 的 React-Native 中使用 styled-component 键入无状态功能组件?