#reactjs #typescript #mixins #higher-order-components #react-tsx
Вопрос:
Приношу извинения за дурацкое название вопроса. Вот подробности.
У меня есть функция HoC/Mixin
export function MyMixin<TOriginalProps>(WrappedComponent: React.ComponentClass<TOriginalProps amp; IExtraProps>): React.ComponentClass<TOriginalProps> {
return class extends React.Component<TOriginalProps> {
public render() {
const value = "something irrelevent to the question"
const props = {...this.props, extraProp: value}
return <WrappedComponent {...props} />;
}
}
}
export interface IExtraProps {
extraProp: string;
}
Теперь это отлично подходит для компонентов, которые имеют свои собственные реквизиты, такие как
class MyComponent extends React.Component<MyProps amp; IExtraProps, MyState>
MyMixin(MyComponent) // this returns React.ComponentClass<TMyProps,any>
однако для компонентов, у которых нет никаких реквизитов (кроме реквизита для «смешивания»), это дает мне что-то немного странное
class MyComponentNoProps extends React.Component<IExtraProps, MyState>
MyMixin(MyComponentNoProps) // this return React.ComponentClass<{children?: React.Node; extraProp: string;}, any>
Я попытался адаптировать функцию MixinFunction, чтобы она принимала значения по умолчанию для параметра типа, но я просто не могу заставить ее принимать.
Есть идеи, как я могу использовать одну функцию (перегрузки тоже были бы хороши) для этого?
Я пробовал перегрузку, у которой нет типа TOriginalProps, но она не устраняется должным образом. Если я определю это первым, то все будут использовать его, а мои компоненты, у которых должны быть реквизиты, — нет. Если я определю его вторым, никто им не воспользуется.
Я предполагаю, что это связано с тем фактом, что я использую React как нечто, выводящее этот странный тип {children: React.Node; extraProps: string} откуда-то (
Ответ №1:
Перегруженная версия, которая IExtraProps
специально нацелена, по-видимому, создает поведение, которое вы ищете:
interface MyProps {
originalProp: number;
}
interface IExtraProps {
extraProp: string;
}
interface MyState {
value: string;
}
export function MyMixin(
WrappedComponent: React.ComponentClass<IExtraProps>
): React.ComponentClass;
export function MyMixin<TOriginalProps>(
WrappedComponent: React.ComponentClass<TOriginalProps amp; IExtraProps>
): React.ComponentClass<TOriginalProps>;
export function MyMixin(
WrappedComponent: React.ComponentClass<any>
): React.ComponentClass {
return class extends React.Component {
public render() {
const value = "something irrelevent to the question"
const props = {...this.props, extraProp: value}
return <WrappedComponent {...props} />;
}
}
}
class MyComponent extends React.Component<MyProps amp; IExtraProps, MyState>{};
class MyComponentNoProps extends React.Component<IExtraProps, MyState>{};
const Test1 = MyMixin(MyComponent);
const Test2 = MyMixin(MyComponentNoProps);
function App() {
return (
<>
<Test1 originalProp={42} /> // OK
<Test2 /> // OK
</>
)
}
Комментарии:
1. Спасибо за предложение, однако, когда я пытаюсь это сделать, я не получаю тех же результатов. По существу, и компонент, и ComponentNoProps вызывают, в которых сначала определяется любая перегрузка, так как и то, и другое может быть выполнено. Оба реализуют IExtraProps, поэтому может применяться не универсальный «фиксированный» метод IExtraProps, и поскольку TOriginalProps может быть просто {}, кажется, что вторая перегрузка тоже соответствует обоим
2. @Dave Я не могу воспроизвести вашу игровую площадку . Не могли бы вы попробовать создать минимальный тестовый случай, в котором это не удастся?