Как разрешить ввод пропса при условии что другой пропс был заполнен?
подскажите пожалуйста, как описать тип, чтобы при отстутсвии определенного ключа, запрещать ввод другого?)
interface Base {
top?: number;
left?: number;
behavior?: "auto" | "smooth"
}
interface OffsetTopProps {
offsetTop?: number;
}
interface OffsetLeftProps {
offsetLeft?: number;
}
// в случае если top был заполнен, то offsetTop можно вводить offsetTop?: number; аналогично с left
пробовал через union сделать, но не получилось
type test = Base | OffsetTopProps | OffsetLeftProps
Ответы (2 шт):
Cамое простое — это использовать миксины и объединения одновременно, миксинами задаем 4 возможных варианта:
leftиtopне заданы- только
leftзадан - только
topзадан leftиtopзаданы
а union позволит TS выбирать между ними. Все работает как нужно в качестве ошибок, но есть и ложка дегтя в этом решении — ошибки отображаются не совсем точно, например:
const t3: test = {
offsetTop: 1
}
Type '{ offsetTop: number; }' is not assignable to type 'test'. Type '{ offsetTop: number; }' is missing the following properties from type 'Base4': top, left
const t4: test = {
offsetLeft: 1
}
Type '{ offsetLeft: number; }' is not assignable to type 'test'. Type '{ offsetLeft: number; }' is missing the following properties from type 'Base4': top, left
(Другие варианты проходят без ошибок можно посмотреть тут)
Если такая точность ошибки не смущает, решение можно считать рабочим.
Весь код:
type Top = {
top: number;
offsetTop?: number;
}
type Left = {
left: number;
offsetLeft?: number;
}
type Behavior = {
behavior?: "auto" | "smooth"
}
interface Base1 extends Behavior {}
interface Base2 extends Top, Behavior {}
interface Base3 extends Left, Behavior {}
interface Base4 extends Top, Left, Behavior {}
type test = Base1 | Base2 | Base3 | Base4
Вот такое решение в итоге:
type TopOptions =
| { top: number; offsetTop?: number; isConsiderHeader?: boolean }
| { top?: never; offsetTop?: never; isConsiderHeader?: never };
type LeftOptions = { left: number; offsetLeft?: number } | { left?: never; offsetLeft?: never };
type Options = ScrollToOptions & TopOptions & LeftOptions;
конечно получаем немного кривые ошибки от ts, но в остальном, вроде все работает