在React Typescript中是否可以将组件prop接口与另一个prop一起使用?

时间:2019-08-15 19:21:54

标签: javascript reactjs typescript

基本上,我希望行injectComponentProps: object动态地绑定到任何injectComponent的prop接口。在这种情况下,它应该是injectComponentProps: InjectedComponentProps,但我希望它是动态的。

I.e一旦在prop中设置了prop injectComponent,然后将injectComponentProps定义为任何injectComponent的props组件。

这可能吗?

interface InjectedComponentProps {
  variant: string
  size: number
}

const InjectedComponent: React.FC<InjectedComponentProps> = (props) => {
  return <Text {...props}>hello</Text>
}

interface ComponentProps {
  injectComponent: React.ReactType
  injectComponentProps: object
}

const Component: React.FC<ComponentProps> = (props) => {
  const InjectedComponent = props.injectComponent
  return (
    <>
      <InjectedComponent {...props.injectComponentProps}/>
    </>
  )
}


const Main: React.FC = () => {
  return (
    <Component
      injectComponent={InjectedComponent}
      injectComponentProps={{ variant: 'footnote', size: 14 }}
    />
  )
}

2 个答案:

答案 0 :(得分:3)

interface InjectedComponentProps {
  variant: string
  size: number
}

const InjectedComponent: React.FC<InjectedComponentProps> = (props) => {
  return null
}

interface ComponentProps<T> {
  injectComponent: React.FC<T>
  injectComponentProps: T
}

const Component = <T extends {}>(props: ComponentProps<T>): JSX.Element => {
  const InjectedComponent = props.injectComponent
  return (
    <>
      <InjectedComponent {...props.injectComponentProps}/>
    </>
  )
}


const Main: React.FC = () => {
  return (
    <Component
      injectComponent={InjectedComponent}
      injectComponentProps={{ variant: 'footnote', size: 14 }}
    />
  )
}

答案 1 :(得分:0)

您应该尝试将object修改为一个constrained generic组件,以推断其类型参数的属性,而不是简单地将类型声明为ComponentProps

通用GetProps使用conditional type inference从组件推断道具,即,推断通用的类型参数。

type GetProps<C extends React.ComponentType<any>> = C extends React.ComponentType<infer P> ? P : any

interface InjectedComponentProps {
  variant: string
  size: number
}

const InjectedComponent: React.FC<InjectedComponentProps> = (props) => {
  return <Text {...props}>hello</Text>
}

// make this a generic type
interface ComponentProps<C extends React.ComponentType<any>> {
  injectComponent: C
  injectComponentProps: GetProps<C>
}

// and use it here
const Component: React.FC<ComponentProps<typeof InjectedComponent>> = (props) => {
  const InjectedComponent = props.injectComponent
  return (
    <>
      <InjectedComponent {...props.injectComponentProps}/>
    </>
  )
}

const Main: React.FC = () => {
  return (
    <Component
      injectComponent={InjectedComponent}
      injectComponentProps={{ variant: 'footnote', size: 14 }}
    />
  )
}