Как пробросить тип компонента-дженерика в другой компонент?
Необходимо сделать компонент-обертку/HOC для компонента (дженерик!) из сторонней библиотеки, чтобы у него тип пропсов был такой-же как и у оборачиваемого компонента и он так же являлся дженериком.
Псевдокод:
import VendorComponent from '@vendorLibrary';
type Entity = {
id: number,
name: string;
anything: object;
}
// Сам компонент используется следующим образом
<VendorComponent<Entity>
valueKey="id" // keyof Entity
// other props
/>
// HOC
type VendorComponentType = typeof VendorComponent;
type Props = React.ComponentProps<VendorComponentType>;
export const WithCustomOptions = (component: React.ComponentType<Props>) => {
const Component = component;
return (props: Props) => {
const customProperty = {
// ...
};
return <Component {...props} someProperty={customProperty} />;
};
};
// Wrapper component
const WrapperComponent = (props: Props) => {
return <VendorComponent {...props} />;
};
export default WithCustomOptions(WrapperComponent);
Проблема возникает, при использовании WrapperComponent
<WrapperComponent
valueKey="id" // Type 'string' is not assignable to type 'undefined'.
// other props
/>
Хотелось бы прокинуть тип пропсов так, чтобы WrapperComponent можно было использовать как дженерик. То есть
<WrapperComponent<Entity>
valueKey="id"
// other props
/>
Изначально планировал типы описать так:
type VendorComponentType = typeof VendorComponent;
type Props = React.ComponentProps<VendorComponentType<Entity>>; // ошибка! VendorComponentType не является дженериком
Возможно ли это реализовать?
Ответы (1 шт):
Автор решения: qwabra
→ Ссылка
interface VendorComponentProps { qwa: string }
let VendorComponent: <T>(p: VendorComponentProps & T) => any
let WrapperComponent: <V extends (...q: any[]) => any, T>(props: Parameters<V>[0] & T) => any
// -,-
VendorComponent = null as any
WrapperComponent = null as any
// -,-
type Entity = {
id: number,
name?: string,
anything?: object,
}
TEST: {
<VendorComponent<Entity> qwa='' id={11} />;;
<WrapperComponent<typeof VendorComponent, {}> qwa='' />;;
<WrapperComponent <typeof VendorComponent, Entity> qwa='' id={11} />;;
}
Wrapper: {
let genWrapper: <C extends (...q: any[]) => any>(Component: C) =>
<T>(props: Parameters<typeof Component>[0] & T) => any
// -,-
genWrapper = Component => {
let WrapperComponent: <T>(props: Parameters<typeof Component>[0] & T) => any
WrapperComponent = props => <Component {...props} />;
return WrapperComponent
};
// -,-
TEST: {
const Wrapper = genWrapper(VendorComponent);;
<Wrapper<Entity> qwa='' id={0} />;;
}
}