-
Notifications
You must be signed in to change notification settings - Fork 130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Типы в defaultProps #2760
Типы в defaultProps #2760
Conversation
312a432
to
f8c6efb
Compare
f8c6efb
to
78448ce
Compare
This reverts commit 78448ce.
В компонентах Давай ещё переименуем |
По поводу smoke тестов (
|
Хмм, странно, |
@HelenaIsh Обсудили эту проблему с Максимом @lossir голосом, решили остановиться на class SomeComponent {
public static defaultProps: Partial<Props> = {
...
}
} Недопонимание произошло по причине того, что я думал, что Как я это понимал:
Как это работает на самом деле:
|
@HelenaIsh Фикс для смок тестов в мастере. |
This reverts commit 7f70215.
Столкнулись с проблемой, что // Снаружи компонента.
// Разделяем пропы на пропы у которых есть значение по умолчанию и все остальные.
type DefaultProps = {
width: number | string;
maxHeight: number | string;
hasShadow: boolean;
...
};
// Пользователи будут получать Partial пропы.
type MenuProps = {
children?: React.ReactNode;
...
} & Partial<DefaultProps>;
// Мы будем пользоваться полноценными пропами.
type MenuComponentProps = MenuProps & DefaultProps;
// Внутри компонента.
class Menu extends React.Component<MenuComponentProps> {
...
public static defaultProps: DefaultProps = {
...
}
...
} Пока что не нашёл изъянов у этого решения.
|
Вот такие вот конструкции выглядят очень устращающе: // ComponentTable.tsx
interface DefaultProps<C, P, S> {
presetProps: DefaultizeProps<C, P>;
presetState: Partial<S>;
}
public static defaultProps: DefaultProps<any, any, any> = {
presetProps: {},
presetState: {},
}; Давай там, где используются дженерики добавим значений по умолчанию для // ComponentTable.tsx
interface DefaultProps<C = any, P = any, S = any> {
presetProps: DefaultizeProps<C, P>;
presetState: Partial<S>;
}
public static defaultProps: DefaultProps = {
presetProps: {},
presetState: {},
}; Таким образом мы во всех компонентах приведём поглощение типа |
В |
И ещё давай вынесем интерфейс компонента в отдельный тип: type AutocompleteInterface = {
/** Функция отрисовки элемента меню */
renderItem: (item: string) => React.ReactNode;
/** Промис, резолвящий элементы меню */
source?: string[] | ((patter: string) => Promise<string[]>);
/** Отключает использование портала */
disablePortal: boolean;
/** Отрисовка тени у выпадающего меню */
hasShadow: boolean;
/** Выравнивание выпадающего меню */
menuAlign: 'left' | 'right';
/** Максимальная высота меню */
menuMaxHeight: number | string;
/** Ширина меню */
menuWidth?: number | string;
/** Отключить скролл окна, когда меню открыто */
preventWindowScroll: boolean;
/** Вызывается при изменении `value` */
onValueChange: (value: string) => void;
/** onBlur */
onBlur?: () => void;
/** Размер инпута */
size: InputProps['size'];
/** value */
value: string;
};
export type AutocompleteProps = Override<InputProps, AutocompleteInterface> & CommonProps & Partial<DefaultProps>; В текущей реализации очень сложно воспринимать что происходит. |
У нас получилась какое-то месиво из ключевых слов |
Нам не нужно дублировать типы из План такой:
То о чём я говорю на примере компонента // Изначальное состояние
export type ButtonProps = {
corners?: number;
disabled?: boolean;
...
size?: ButtonSize;
type?: ButtonType;
use?: ButtonUse;
} & CommonProps; // С типом DefaultProps
// Пользовательский тип ButtonProps
export type ButtonProps = {
corners?: number;
disabled?: boolean;
...
} & CommonProps & Partial<DefaultProps>;
type DefaultProps = {
use: ButtonUse;
size: ButtonSize;
type: ButtonType;
}
// Внутренний тип ButtonComponentProps
type ButtonComponentProps = ButtonProps & DefaultProps; |
18e6c4b
to
7394927
Compare
Создал пулл-реквест в парковку удаляющий |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Я вижу, что это решение одновременно двух проблем, IF-284 и #2553.
Оно работает, но слишком радикально. Разделение интерфейса пропов на много частей уменьшает читаемость в данном случае. Придется в голове собирать все по кусочкам. Плюс, поддерживать код и писать новый по этим правилам будет непросто. Уже сейчас в ValidationContainer
объявление пропа disableSmoothScroll
дублируется в двух местах. Нет шансов что в этом всегда будет порядок.
Решаемые проблемы того не стоят. Они все исходят из особенностей defaultProps
, от использования которых мы сможем вовсе отказаться с переходом на функциональные компоненты. Предлагаемые изменения тогда станут не нужны.
Я бы обе проблемы решил просто в лоб, локально. Для #2553 cделал бы все пропы опциональными, порешав проблемы с линтом дополнительными проверками в нашем коде. А для IF-284 указал бы везде корректный тип для defaultProps
руками, например.
От createPropsGetter
можно отказаться.
С этим не соглашусь по нескольким причинам (которые мы даже кажется уже обсуждали):
Я вижу два вероятных решения этой проблемы:
Я голосую за второй вариант, так как оперативно закрыть задачу у нас уже не получилось |
Зачем их возвращать? У нас проблема с типом пропов, у которых есть дефолтные значения (#2553). Их нужно перманентно порешать, сделав по-настоящему опциональными.
Согласен. Со "всеми" пропами я погорячился. Нужно сделать опциональными только те, которые сейчас в типах указаны обязательными, но имеют дефолтные значения (по сути - необязательные). Это корень проблемы #2553. P.S: на счет обязательности
Это цена решения проблемы на нашей стороне. Не такая уж и большая. До этого мы решили предоставить пользователям мириться с ней, что и привело к #2553. С тем, что можно оставить как есть до перехода на функциональные - согласен. |
В таком случае, мы кстати можем убить двух зайцев сразу: сейчас сделать все пропы, которые есть в
В документации |
Тогда, сходимся на том, что, что сейчас делаем все пропы, которые есть в
Это какая-то отдельная задача, раньше она не звучала. Можно сделать в функциональных, если она действительно стоит.
Да, по факту так. Но с моей точки зрения, поддержка a11y, скраппинга и др. - это все дополнительный функционал, который мне может быть сознательно не нужен. В этом случае, меня насильно будут заставлять передавать пустую строку. И даже в остальных случаях, думаю, многие будут это делать. Тоже не очень хорошее API, плохой DX. Я бы сделал такой проп опциональным, снабдив соответствующим правилом для eslint. |
fix IF-284
Решение
Было принято решение разделять пропы на пропы у которых есть значение по умолчанию (DefaultProps) и все остальные.
Экспортировать будем 'частичные пропы':
Мы будем пользоваться полноценными пропами:
type ComponentNameComponentProps = ComponentNameProps & DefaultProps;
Дополнительно это позволило избавиться от
createPropsGetter