Реализация обработчика сообщений в TypeScript с использованием сопоставленных типов

Я пытаюсь реализовать обработчик сообщений, используя сопоставленные типы. Проблема в том, что функция handleMessage ниже не компилируется. Я понимаю, почему он не печатает проверку, но я думаю, что это разумный вариант использования. Возможно ли вообще реализовать handleMessage или подобное в TypeScript?

type Message = { id: "A", value: string } | { id: "B", value: number };
type MessageIds = Message["id"];
type MessageCase<K extends MessageIds> = Message & { id: K };

type MessageHandler<K extends MessageIds> = (message: MessageCase<K>) => MessageCase<K>;

type MessageHandlers = {
    readonly [K in MessageIds]: MessageHandler<K>;
}

const messageHandlers: MessageHandlers = {
    A(message: MessageCase<"A">): MessageCase<"A"> {
        return {
            id: "A",
            value: message.value.toUpperCase(),
        };
    },

    B(message: MessageCase<"B">): MessageCase<"B"> {
        return {
            id: "B",
            value: message.value * 2,
        };
    },
};

function handleMessage<K extends MessageIds>(message: MessageCase<K>): MessageCase<K> {
    return messageHandlers[message.id](message);
}

person MI3Guy    schedule 18.03.2021    source источник
comment
Пожалуйста, дайте мне знать, если эта статья полезна catchts.com/publish-subscribe   -  person captain-yossarian    schedule 18.03.2021
comment
Не совсем. Ключевым моментом здесь является возможность сделать это без проверки каждого случая вручную.   -  person MI3Guy    schedule 18.03.2021
comment
MessageCase неправильный, потому что const x: MessageCase<'A'> = { id: 'A', value: '1' }   -  person captain-yossarian    schedule 18.03.2021
comment
Как так? Я попробовал этот код, и он отлично компилируется.   -  person MI3Guy    schedule 18.03.2021
comment
мой плохой) это работает   -  person captain-yossarian    schedule 18.03.2021
comment
Это еще один случай неспособности компилятора обработать то, что я назвал коррелированными типами объединения; см. microsoft/TypeScript#30581. Вам придется использовать что-то вроде утверждения типа, чтобы это скомпилировалось, когда бремя обеспечения безопасности типов переносится с компилятора (который не может этого сделать здесь) на вас (так что будьте осторожны). Поставьте лайк этому.   -  person jcalz    schedule 18.03.2021