React.FC 中的 GenericType<Props<T>>

Jol*_*lly 11 typescript reactjs react-hooks

我正在构建一个基于 Hooks 的 React 应用程序,也利用 TypeScript。
我编写了一个呈现列表的组件,其中props它期望props.items哪种类型是通用的T

export interface ISelectableListProps<T extends { isDisableInList?: boolean }> {
    /** Specifies the item of the list. */
    items: T[];
    /** Unique REACT key used to re-initialize the component. */
    key?: React.ReactText;
    /** Specifies the template of each item. */
    itemTemplate: (item: T) => JSX.Element;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在界面中,T还 extends { isDisableInList?: boolean },这是因为每个项目都可能具有该属性,用于禁用列表中的项目。

现在,对于 SelectableList 组件的问题,我想这样写:

const SelectableListComponent: React.FC<ISelectableListProps<T>> = <T extends {}>(props) => { ... }
Run Code Online (Sandbox Code Playgroud)

但是 TypeScript 给了我一个错误和一个问题:

  1. 错误:未找到类型T, in ;ISelectableListProps<T>
  2. 问题:props不再推断 的类型:它具有any。相反,通过删除<T extends {}>props类型被推断为React.PropsWithChildren<ISelectableListProps<any>>;

我发现的唯一解决方法是定义 a ItemType,如下所示:

type ItemType = { isDisableInList?: boolean } & { [key: string]: any };
Run Code Online (Sandbox Code Playgroud)

然后像这样编写组件:

const SelectableListComponent: React.FC<ISelectableListProps<ItemType>> = props => { ... }
Run Code Online (Sandbox Code Playgroud)

但是这样做,在使用组件时,props.items预计会是ItemType[],而不是泛型类型。事实上,我想这样调用该组件:

<SelectableList<MyType> items={...} itemTemplate={...} />
Run Code Online (Sandbox Code Playgroud)

但是,正如我所说,这些项目预计将是ItemType在此输入图像描述

顺便说一句,没有给出错误,因为ItemTypehas & { [key: string]: any },但在我看来“hacky”,几乎就像使用any.

有什么办法可以实现我想要的吗?

Tit*_*mir 9

没有办法用来React.FC定义通用组件。您可以只使用简单的函数定义或箭头函数,但让 TS 推断类型:

export interface ISelectableListProps<T extends { isDisableInList?: boolean }> {
    /** Specifies the item of the list. */
    items: T[];
    /** Unique REACT key used to re-initialize the component. */
    key?: React.ReactText;
    /** Specifies the template of each item. */
    itemTemplate: (item: T) => JSX.Element;
}

const SelectableListComponent = <T extends {}>(props: ISelectableListProps<T>) => <></>


Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • 这是一个非常好的解决方法,但我的 ESLint 抱怨我没有给出返回类型。因此,我必须添加 `: React.Element | 空=&gt;`。现在时间已经过去了,也许您有更好的解决方法? (2认同)