Я бы подошел к этому, используя «карту поиска типов», чтобы связать воедино метод доставки и связанный с ним объект действия.Поэтому я бы добавил еще один тип, подобный этому:
type DeliveryActionTypes = {
"notification": INotificationAction;
"text": ITextMessageAction;
"email": IEmailAction;
}
Этот тип просто отображает правильное имя метода в тип объекта действия.Затем вы можете заменить объявления для DeliveryMethod
и DeliveryActions
на:
type DeliveryMethod = keyof DeliveryActionTypes;
type DeliveryActions = DeliveryActionTypes[keyof DeliveryActionTypes];
Это позволит вам легко найти правильное действие, если вы знаете имя метода.Вы можете использовать это в вашем IDeliveryObject
, чтобы убедиться, что эти два типа соответствуют:
interface IDeliveryObject<T extends DeliveryMethod> {
type: T;
// This is the type lookup, note the `DeliveryActionTypes[T]` part.
deliveryItems: Array<DeliveryActionTypes[T]>;
}
Теперь вы можете упростить сигнатуру для функции sendDelivery
, так как теперь все, что ей нужно, это имя метода:
function sendDelivery<K extends DeliveryMethod>(state: IDeliveryObject<K>) {
console.log(state)
}
При всем этом вы получите ошибку, если типы не совпадают:
sendDelivery({
type: 'notification',
deliveryItems: [
{
type: 'email',
to: 'fake@email.com', // <-- error on this line, see below
subject: '1235-67890',
body: 'Here is a notification'
}
]
})
Type '{ type: "email"; to: string; subject: string; body: string; }'
is not assignable to type 'INotificationAction'.
Как выКак видите, Typescript правильно заключает, что элементы в массиве должны иметь тип INotificationAction
, и выдает ошибку, когда их нет.