#typescript #typescript-typings #typescript-generics
#машинописный текст #typescript-типизации #typescript-дженерики
Вопрос:
У меня есть следующие интерфейсы:
interface ButtonProps {
name: string;
}
interface IconButtonProps {
name: string;
icon: string;
}
Я пытаюсь создать тип для следующего компонента:
<MyGenericComponent component={button} name="button">...
<MyGenericComponent component={iconButton} name="icon-button" icon="icon">...
Идея в том, что я не могу ввести интерфейс, который будет представлять MyGenericComponentProps
, чтобы он мог принимать компонент react в component
prop, если все остальные реквизиты, предоставленные ему, являются теми, которые принимает данный компонент!
Что — то вроде этого:
interface MyGenericComponentProps<T> extends T {
component: React.FC<T>;
}
…где T
выше может быть ButtonProps
или IconButtonProps
. Я знаю, что не могу расширить T
, потому что он статически неизвестен, но тогда как мне убедиться, что остальные данные реквизита относятся к одному ButtonProps
или IconButtonProps
?
ОБНОВЛЕНИЕ: вот определение компонента после ответа:
import React from 'react';
import { ButtonProps, IconButtonProps } from '@material-ui/core';
type MyGenericComponentProps<T> = {
component: React.FC<T>;
} amp; {
[key in keyof T]: T[key];
};
const MyGenericComponent = <T extends object>({ component, ...props }: MyGenericComponentProps<T>) => {
// ... more code here
const Component = component;
return <Component {...props} />;
};
export default MyGenericComponent;
Ответ №1:
Если не имеет смысла, какой объект TS будет использоваться (тип или интерфейс), вы можете ввести его как тип вместо интерфейса:
type MyGenericComponentProps<T> = {
component: React.FC<T>;
} amp; {
[key in keyof T]: T[key];
}
[ОБНОВЛЕНИЕ]:
Вам нужно изменить и даже упростить некоторые фрагменты:
type MyGenericComponentProps<T> = {
component: React.FC<T>;
props: T;
}
const MyGenericComponent = <T extends object>({component: Component, props}: MyGenericComponentProps<T>) => {
// ... more code here
return <Component {...props}/>;
};
Комментарии:
1. Спасибо. Проблема в том, что при попытке реализовать
MyGenericComponent
его после я получаю следующую ошибку: введите ‘Pick<MyGenericComponentProps<T>, Исключите<keyof T, «component»>>’ не может быть присвоен типу ‘IntrinsicAttributes amp; T amp; { дочерние элементы?: ReactNode; }’. Тип ‘Выбрать<MyGenericComponentProps<T>, исключить<keyof T, «компонент»>>’ не может быть присвоен типу ‘T’. ‘Выбрать<MyGenericComponentProps<T>, исключить<keyof T, «component»>>’ можно назначить ограничению типа ‘T’, но ‘T’ может быть создан с другим подтипом ограничения ‘MyGenericComponentProps’.ts(2322)2. К вашему сведению, то, что я пытаюсь сделать внутри
MyGenericComponent
, заключаетсяlet Component = component
в том<Component {...props} />
, что я получаю ошибку выше.3. Пожалуйста, покажите, как вы определяете
MyGenericComponent
.4. Я только что обновил вопрос, чтобы поделиться полным определением. Заранее спасибо.
5. Спасибо, но таким образом у меня нет
props
как части самих свойств интерфейса. Я не хочу передавать реквизит вprops
объекте, а напрямую.
Ответ №2:
interface ButtonProps {
name: string;
}
interface IconButtonProps extends ButtonProps{
icon?: string;
}
и
interface MyGenericComponentProps<IconButtonProps>{
component: React.FC<IconButtonProps>;
}
не знаю о react, но с помощью typescript вы можете расширять интерфейсы и объявлять необязательные свойства. Тогда это будет принимать ButtonProps и IconButtonProps