Reputation: 28329
Basically, I want line injectComponentProps: object
to be tied dynamically to whatever the injectComponent's prop interface is. In this case, it would be injectComponentProps: InjectedComponentProps
, but I want it to be dynamic.
I.e Once prop injectComponent is set in , injectComponentProps is then defined to whatever injectComponent's components props are.
Is this possible?
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 }}
/>
)
}
Upvotes: 3
Views: 1474
Reputation: 3449
Instead of declaring the type simply as object
, you should try modifying ComponentProps
into a constrained generic component that infers the props of its type parameter.
The generic GetProps
uses conditional type inference to infer props from a component, i.e., infer type parameter of a generic.
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 }}
/>
)
}
Upvotes: 0
Reputation: 28329
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 }}
/>
)
}
Upvotes: 3