打字稿:如何键入React抽象组件?

时间:2020-03-23 09:23:06

标签: reactjs typescript

我在尝试在Typescript中键入抽象组件时遇到了问题(来自大量流程经验。)-以下示例正在使用Typescript 3.8.3

代码是:

const useSlot = (): [React.ReactNode, React.ComponentType] => {
    const slotRef = useRef();
    const Slot = ({ children }: { children: React.ReactNode }): React.ReactNode =>
        slotRef.current ? createPortal(children, slotRef.current) : null;

    return [<div ref={slotRef} />, Slot];
};

export default useSlot;

用法是:

const [slotLocation, Slot] = useSlot();

return (
    <div>
        {slotLocation}
        <Slot>Some content</Slot>
    </div>
);

我的问题是我找不到在线搜索的任何通用React组件类型...在流程中,我们将使用React.AbstractComponent<Props>类型来覆盖任何种类的React组件。但是我在Typescript中找不到替代方法,我见过React.ComponentReact.FCReact.ComponentType;但他们都不在工作。显然,它不允许从这些组件类型返回ReactNode(特别是string)。

error TS2345: Argument of type 'ReactNode' is not assignable to parameter of type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.
  Type 'string' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.

20         render(slotLocation)
                  ~~~~~~~~~~~~

error TS2322: Type '({ children }: { children: React.ReactNode; }) => React.ReactNode' is not assignable to type 'ComponentType<{}>'.
  Type '({ children }: { children: React.ReactNode; }) => React.ReactNode' is not assignable to type 'FunctionComponent<{}>'.
    Type 'ReactNode' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.
      Type 'string' is not assignable to type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<any, any, any>)>'.

12     return [<div ref={slotRef} />, Slot];

我们如何键入可以返回任何类型的React节点的通用组件类型?

1 个答案:

答案 0 :(得分:1)

首先,您需要输入ref并将其传递给createPortal

第二种Slot的返回类型是ReactPortal而不是ComponentType

您还应该让TypeScript进行尽可能多的推断,仅键入TypeScript无法推断的内容

我要返回数组as const来键入元素的位置,而不是显式地键入useSlot的返回类型

const useSlot = () => {
  const slotRef = useRef<HTMLDivElement>(null)
  const Slot = ({ children }: { children: React.ReactNode }) =>
    slotRef.current ? createPortal(children, slotRef.current) : null

  return [<div ref={slotRef} />, Slot] as const
}