Как сузить кортежи машинописи на основе значений в другом объекте? - PullRequest
0 голосов
/ 02 мая 2020

Краткий обзор моей цели высокого уровня: у меня есть система, которая обрабатывает события на основе кодов событий, которые я не контролирую, но могу перечислять. Каждое событие может привести к различным типам действий в моей системе. Я пишу машинопись для обработки этих событий. Я хотел бы написать код, который имеет следующие свойства:

  1. Сильная время компиляции гарантирует, что код события обрабатывает все события для данного пути
  2. Единственный источник истины для информация о событиях и свойства этих событий.

Свойства моих событий, которые определяют мое поведение, выглядят примерно так:

type EventProperties = (
    shouldDoX: boolean;
    someOther: string;
    propertiesHere: number;
};

Начиная с конечной цели того, что я хочу: я ' я хотел бы иметь возможность делать что-то вроде

function handleEvent(eventCode: EventCode) {
  if (EventInfo[eventCode].shouldDoX) {
    doX(eventCode);
  } else {
    // Type narrowed to events where shouldDoX is false
  }

  doSomethingCommonToAllEvents(eventCode);
}

function doX(eventCode: EventCodeThatRequiresX) {
  console.log('I did X');
}

Я начал работать над определением типа, чтобы достичь этой цели, и я думаю, что в идеале оно могло бы быть организовано так:

export const EventCodes = ['CRE', 'DEL'] as const;
export type EventCode = typeof EventCodes[number];

export const EventInfo: {
    [TDog in EventCode]: {
        shouldDoX: boolean;
        otherProp: string;
    };
} = {
    CRE: {
        shouldDoX: true,
        otherProp: 'foo'
    },
    DEL: {
        shouldDoX: false,
        otherProp: 'bar'
    }
};

Это кажется лучшим подходом, так как есть принудительное выполнение во время компиляции, обеспечивающее правильную настройку события. К сожалению, я не могу понять, как писать типы для EventCodeThatRequiresX и EventCodeThatDoesNotRequireX, чтобы их объединения определялись содержимым объекта EventInfo. Это возможно? Кажется, что ограничение заключается в том, что следующий тип оценивается как логический, а не как ложный, что, как я полагаю, потребовало бы использования условных типов + сопоставленных типов для генерации желаемых типов.

type ShouldBeFalse = typeof EventInfo.DEL.shouldDoX;

Если это не так возможно, как бы вы предложили записать эти константы / перечисления / типы так, чтобы они сохраняли два свойства, упомянутых выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...