В typescript, как вы выражаете тип объекта, где одним из полей является имя типа?

#typescript

Вопрос:

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

 type EventMap = {
  created: { created: string },
  updated: { updated: string }
}

type Payload<T extends keyof EventMap> = {
  event_id: string;
  event: T;
  data: EventMap[T];
};

type Payloads = Payload<'created'> | Payload<'updated'>
 

Такое чувство, что я не должен повторять created и updated . Но, конечно Payload<keyof EventMap> , это не совсем правильно, так как это позволит любую комбинацию.

Ответ №1:

Вы можете сделать что-то вроде следующего:

 type Payloads = { [K in keyof EventMap]: Payload<K> }[keyof EventMap]
 

Игровая площадка

Или создайте Payloads тип EventMap непосредственно из:

 type Payloads = {
    [K in keyof EventMap]: {
        event_id: string;
        event: K;
        data: EventMap[K];
    }
}[keyof EventMap]
 

Игровая площадка


 // works
const x: Payloads = {
    event_id: 'x',
    event: 'created',
    data: {
        created: 's'
    }
}

// works
const y: Payloads = {
    event_id: 'x',
    event: 'updated',
    data: {
        updated: 's'
    }
}

// error due to mixed updated and created
const z: Payloads = {
    event_id: 'x',
    event: 'updated',
    data: {
        created: 's'
    }
}