如何在React中引用组件的道具?

时间:2019-04-02 22:59:50

标签: reactjs typescript

我有一个可以接受另一个组件作为道具的组件。不管它有其他什么道具,它都会将它们传递给子组件。看起来就是这样:

interface FormGroupProps extends BasicInputProps<any> {
  label: string
  name: string
  Component: ComponentType<BasicInputProps<any>>
}

export const FormGroup: SFC<FormGroupProps> = ({
  label,
  Component,
  ...props
}) => (
  <RBSFormGroup>
    <Label>{label}</Label>
    <Component {...props} />
  </RBSFormGroup>
)

您可以在FormGroupProps中看到,我告诉TS Component将只接受某种类型的道具。这是不理想的,因为有时我需要传递不一定与该签名匹配的组件。

我可能只写ComponentType<any>,但这太宽松了。我希望能够编写类似ComponentType<Component['props']>之类的东西,但据我所知没有。

有没有办法引用元件的props类型?还是我需要手动传递一个通用类型来实现这一目标?

1 个答案:

答案 0 :(得分:0)

New typings introduced to @types/react in response to React 16.6 include the following types:

type ComponentProps<T extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> =
    T extends JSXElementConstructor<infer P>
        ? P
        : T extends keyof JSX.IntrinsicElements
            ? JSX.IntrinsicElements[T]
            : {};

type ComponentPropsWithRef<T extends ElementType> =
    T extends ComponentClass<infer P>
        ? PropsWithoutRef<P> & RefAttributes<InstanceType<T>>
        : PropsWithRef<ComponentProps<T>>;

type ComponentPropsWithoutRef<T extends ElementType> = PropsWithoutRef<ComponentProps<T>>;

Which reference the types of a component's props. You should be able to achieve your desired interface using one of these new types:

interface FormGroupProps {
    label: string;
    name: string;
    Component: React.ComponentProps<typeof Component>;
}

This is super handy if you want to avoid exporting prop interfaces all over the place, or for extracting props interfaces from libraries which don't export them. Also, unlike Component['props'], it also works for functional components.