Как типизировать объект в зависимости от указанного значения в свойстве?

Есть общий интерфейс(SpinnerInterface) в котором перечислены все допустимые свойства объекта.

Но свойство(statusCheck) должно быть обязательным только в случае если type будет указан как progressLoading

interface SpinnerInterface{
  fillParent: boolean;
  type: SpinnerType;
  statusCheck: StatusProgress; // только для type:progressLoading
}

enum SpinnerType {
  blockedPage,
  progressLoading
}

Типизация через Omit исключает свойство для всех свойств.

type ExcludeStatus = Omit<SpinnerInterface, 'statusCheck'>;

Я предполагаю что нужно добавить еще какую то обработку перед ExcludeStatus но я незнаю в какую сторону нужно копать(гуглить).

Буду рад вашим идеям/предположениям/ссылкам. Большое спасибо за помощь.


Ответы (1 шт):

Автор решения: ThisMan

Можно создать общий тип с кастингом св-ва + несколько типов, которые расширяют базовый и там прописать условие для динамических полей

Пример

enum SpinnerType {
    BASE = 'base',
    PROGRESS_LOADING = 'progressLoading',
}

interface StatusProgress {
    loading: boolean;
}

// Базовый тип
interface Spinner<T = SpinnerType> {
    fillParent: boolean;
    type: T;
}

interface SpinnerBase extends Spinner<SpinnerType.BASE> {};
interface SpinnerWithProgress extends Spinner<SpinnerType.PROGRESS_LOADING> {
    statusCheck: StatusProgress;
}

type Spinners = SpinnerBase | SpinnerWithProgress;

// Тут все ок без св-ва statusCheck
const spinnerBase: SpinnerBase = {
    type: SpinnerType.BASE,
    fillParent: true,
}

// Тут ошибка, что statusCheck св-ва нет
const spinnerWithProgressWrong: SpinnerWithProgress = {
    type: SpinnerType.PROGRESS_LOADING,
    fillParent: false,
}

const spinnerWithProgressRight: SpinnerWithProgress = {
    type: SpinnerType.PROGRESS_LOADING,
    fillParent: false,
    statusCheck: { loading: false }
}

Из плюсов, в switch/case по type тип будет автоматические внутри case определяться)

→ Ссылка