(лево ИЛИ право) ИЛИ (верх ИЛИ низ)
// Левое ИЛИ правое значение.
type OffsetHorizontal =
| { left: number; right?: never; }
| { right: number; left?: never; }
// Верхнее ИЛИ нижнее значение.
type OffsetVertical =
| { top: number; bottom?: never; }
| { bottom: number; top?: never; }
// Горизонтальные значения, с запретом использования с вертикальными.
type OffsetHorizontalOnly = OffsetHorizontal & {
top?: never;
bottom?: never;
}
// Вертикальные значения, с запретом использования с горизонтальными.
type OffsetVerticalOnly = OffsetVertical & {
left?: never;
right?: never;
}
// OffsetHorizontalOnly ИЛИ OffsetVerticalOnly.
type Offset = OffsetHorizontalOnly | OffsetVerticalOnly;
// Верно:
// { left: 100 }
// { right: 100 }
// { top: 100 }
// { bottom: 100 }
// Неверно:
// { left: 100, right: 100 }
// { top: 100, bottom: 100 }
// { left: 100, top: 100 }
// { right: 100, top: 100 }
// { left: 100, bottom: 100 }
// { right: 100, bottom: 100 }
Если понадобиться вариант с И/ИЛИ между осями, то можно так реализовать:
// Левое ИЛИ правое значение.
type OffsetHorizontal =
| { left: number; right?: never; }
| { right: number; left?: never; }
// Верхнее ИЛИ нижнее значение.
type OffsetVertical =
| { top: number; bottom?: never; }
| { bottom: number; top?: never; }
// OffsetHorizontal И/ИЛИ OffsetHorizontal.
type Offset =
| OffsetHorizontal
| OffsetVertical
| (OffsetHorizontal & OffsetVertical);
// Верно:
// { left: 100 }
// { right: 100 }
// { top: 100 }
// { bottom: 100 }
// { left: 100, top: 100 }
// { right: 100, top: 100 }
// { left: 100, bottom: 100 }
// { right: 100, bottom: 100 }
// Неверно:
// { left: 100, right: 100 }
// { top: 100, bottom: 100 }